How to make a DEB package with diacritics and spaces in filenames


While most of bash scripts for Linux could serve as examples of command line versatility and efficiency, this does not. It fixes an annoying and persistent bug in the DEB package management. The package building process fails if there is any file with "unsafe" name in the package, i. e. having diacritics and/or spaces in the filename. (I must admit that packaging for ubuntu is a disappointing experience for me.) This guide is a dirty workaround, but you may find it useful.

Originally I wanted to distribute (several hundreds of) LibreOffice templates using my Ubuntu PPA. However, I did not find any direct way to distribute files with "unsafe" names and I needed to. Therefore I wrote this script, which renames the files to "safe" names and after installing the package it ensures the files are renamed to their final, "unsafe" name.

This script accepts a "data" directory containing any subdirectory structure. It generates appropriate debian/install, debian/postinst and debian/prerm files.

Limitations and warnings

IMPORTANT NOTE 1: This script renames your files to "safe" version. Make a copy of the data directory and do all changes there. Then copy the directory back and run the script only once.

IMPORTANT NOTE 2: This script does NOT check for existing system files or directories. E. g., if you pack anything in a data/ěťč/... directory, it will be installed as /etc/... and then the directory /etc/ will be renamed to /ěťč/, rendering the system unusable. Check everything for this!

The script


IFS=$(echo -en "\n\b")

function safe_filename 
		FILEPATH=`echo ${1%/*}`
		FILENAME=`echo ${1##*/} | cstocs utf8 ascii | sed -e 's/\s/_/g'`

## Rename all directories to DEB-safe name
rm -f postinst.part 
rm -f prerm.part 
for ORIG in `find data | sed -e 's/data\///g' | tac`
		# mv data/"$ORIG" data/"`safe_filename "$ORIG"`"
		TO=`safe_filename "/$ORIG"`
		if [ "$FROM" != "$TO" ]
			mv data/"$FROM"  data/"$TO"
			echo 'mv "'$FROM'"  "'$TO'"' >> prerm.part
			echo 'mv "'$TO'"  "'$FROM'"' >> postinst.part

## Prepare the postinst script to rename all directories to the original name
touch debian/postinst
chmod +x debian/postinst
sed -e '/==\s*REWRITTEN\s*FROM\s*HERE\s*==/q' -i debian/postinst
tac postinst.part >> debian/postinst
rm postinst.part

## Prepare the prerm script to rename all directories to DEB-safe name again
## (This is needed for the apt system to remove all files correctly.)
touch debian/prerm
chmod +x debian/prerm
sed -e '/#\s*==\s*REWRITTEN\s*FROM\s*HERE\s*==/q' -i debian/prerm
cat prerm.part >> debian/prerm
rm prerm.part

## Finally index all files in the debian/install
rm -f debian/install
for FILE in `find data -type f  | sed -e 's/data\///g'`
		echo "data/$FILE /${FILE%/*}" >> debian/install


Get acquainted with the basic ubuntu packaging guide. Prepare your PPA and files in the "debian" directory for your package.

If you use anything in the "debian/postinst" or "debian/prerm" scripts, end these scripts with a line containing "# == REWRITTEN FROM HERE ==".

Prepare your directory structure in a "data" directory. Basically it is a patch to the directory structure of the system to be installed to. Any filenames should be accepted, but take care at "IMPORTANT NOTE 2".

Make a backup of your directory structure somewhere. Move the whole directory next to the debian directory. (Now you have "debian" and "data" directories side by side.)

Run this script and pack the DEB package as usual. After installation, even the files with "unsafe" names should be installed properly!

Note: if you make any changes of the files later, do not change the data directory directly. Perform the changes on a copy with "unsafe" names and then copy it instead of the data directory. The reason is that each time the script is run, it renames the files to "safe" names (see "IMPORTANT NOTE 1").

© Filip Dominec | Last edited: 2011-11-12 | go to index➤