How to make a DEB package with diacritics and spaces in filenames |
IntroductionWhile 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 warningsIMPORTANT 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#!/bin/bash OLDIFS=$IFS IFS=$(echo -en "\n\b") function safe_filename { FILEPATH=`echo ${1%/*}` FILENAME=`echo ${1##*/} | cstocs utf8 ascii | sed -e 's/\s/_/g'` #echo $FILEPATH/$FILENAME echo $FILEPATH/$FILENAME } ## 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` do # mv data/"$ORIG" data/"`safe_filename "$ORIG"`" FROM="/$ORIG" TO=`safe_filename "/$ORIG"` if [ "$FROM" != "$TO" ] then mv data/"$FROM" data/"$TO" echo 'mv "'$FROM'" "'$TO'"' >> prerm.part echo 'mv "'$TO'" "'$FROM'"' >> postinst.part fi done ## 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'` do echo "data/$FILE /${FILE%/*}" >> debian/install done UsageGet 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"). |