A self-extracting tar archive

If you want to create a self-extracting archive, or a self-contained executable, you may create a shell script which contains packed data, and can extract those data automatically. You proceed as follows.

Creating the archive

The archive is created with name $TGZ_NAME, containing the files $FILES_TO_PACK

$ tar czf $TGZ_NAME $FILES_TO_PACK
Creating the installer script

The installer script is a normal bash script, which can access the packed data in a special way.

BUILTIN_PACKAGE_SEARCH_RES=$(grep -hnam1 '^TGZFILE_DATA:[^:]\+:$' $0)
if [ $? -eq 0 ]; then
    BUILTIN_PACKAGE_LINE=$(echo "$BUILTIN_PACKAGE_SEARCH_RES" | cut -d ':' -f 1)
    BUILTIN_PACKAGE_NAME=$(echo "$BUILTIN_PACKAGE_SEARCH_RES" | cut -d ':' -f 3)
else
    # error
fi

We have also recovered the original package name, which can contain useful information.

The package is then unpacked with:

START_LINE=$(($BUILTIN_PACKAGE_LINE + 1))
tail -n +$START_LINE $0| tar xzvf - -C "$DEST_DIR" >> "$LOG_FILE_NAME" 2>&1

Where $DEST_DIR is a destination directory (existing – it may be a temporary directory or something else) and $LOG_FILE_NAME is a log file for the result of the unpacking. We can avoid it with:

tail -n +$START_LINE $0| tar xzvf - -C "$DEST_DIR" >> "/dev/null" 2>&1

At the end you may also self-destruct the script with:

rm $0
Packaging everything

Assume that the installer script is called script.sh – any name is ok since it won’t appear in the final product.

$SH_NAME is the name of the resulting package.

$ cat script.sh > $SH_NAME$ cat "TGZFILE_DATA:$TGZ_NAME:" >> $SH_NAME$ cat $TGZ_NAME >> $SH_NAME
$ chmod +x $SH_NAME

At the end, $SH_NAME will be an executable script, able to access the packaged data.

Leave a Reply