gzexe turns an executable into a self-extracting shell script, which is a neat trick until you forget which file is the backup. This guide compresses one executable in place, checks that its wrapper still runs the program, and shows how to restore the original. The local system provides gzexe from gzip 1.12-1ubuntu3.2.
Allow about five minutes for a small test file; a large program takes longer. You need a readable executable, write access to its directory, and enough temporary disk space for a working copy. The normal examples are unprivileged. Use sudo only when the executable sits in a directory you cannot write, and remember that changing a system executable can disrupt other users and services.
Checkpoint: Do not start with a production binary. Make a copy or use a disposable executable first, then confirm the result before removing its backup.
Confirm which implementation will run and inspect the file you intend to change. Keep the target path explicit: a typo here can compress the wrong executable, and a relative path gets confusing if a script changes directory.
$ command -v gzexe
/usr/bin/gzexe
$ gzexe --version
gzexe (gzip) 1.12
$ TARGET=/path/to/your/executable
$ test -r "$TARGET" && test -x "$TARGET" && file "$TARGET"
$ ls -l -- "$TARGET"
The manpage describes the operand as one or more executable names. The installed script also accepts --help and --version, although the documented compression and decompression switch is -d.
Run the program before changing it and save the output, or another meaningful check. A command with side effects makes a poor test; for a harmless command-line tool, a version query or read-only operation works well.
$ "$TARGET" --version
$ printf 'exit status: %s\n' "$?"
exit status: 0
Replace --version with arguments that are valid for your program. Do not invent a test option just to follow this example. If the baseline fails, stop and fix that first.
Warning: This changes the target in place. gzexe keeps the previous file as TARGET~, then replaces the target with a self-uncompressing shell script. Make sure that filename is not already a backup you need.
$ gzexe -- "$TARGET"
/path/to/your/executable: ... replaced with stdout
$ ls -l -- "$TARGET" "$TARGET~"
$ head -n 2 -- "$TARGET"
#!/bin/sh
skip=49
The exact compression summary, file sizes and skip value vary. What matters is that both files exist and the first now starts as a shell script. The original executable lives in TARGET~; the compressed file is no longer a native binary.
Execute the same safe baseline check. The wrapper extracts the compressed payload into a temporary directory, starts it, and cleans up after a short delay, so expect extra startup time on frequent invocations.
$ "$TARGET" --version
your-program 1.2.3
$ printf 'exit status: %s\n' "$?"
exit status: 0
$ file "$TARGET" "$TARGET~"
/path/to/your/executable: POSIX shell script, ASCII text executable
/path/to/your/executable~: ... executable
Use output appropriate to your program, not the illustrative version string. Also check permissions and ownership when they matter:
$ stat -c '%A %a %U:%G %n' -- "$TARGET" "$TARGET~"
-rwxr-xr-x 755 operator:operator /path/to/your/executable
-rwxr-xr-x 755 operator:operator /path/to/your/executable~
The command tries to retain attributes, but its manpage warns you may need to repair them with chmod or chown. Do not copy these example owner values blindly.
The compressed file is a shell script. When it runs, it finds gzip and helpers such as basename, chmod, ln, mkdir, mktemp, rm, sleep and tail through PATH. A manipulated PATH can make the wrapper run the wrong helper.
$ printf '%s\n' "$PATH"
$ type gzip basename chmod ln mkdir mktemp rm sleep tail
Run the wrapper with a trusted, minimal path when testing it in a sensitive context. Use absolute paths for the target and never place untrusted directories before system directories. Never use gzexe on a setuid or setgid executable: the installed script refuses those permission bits, and a compressed shell wrapper would be an unsafe boundary regardless.
If the result is unsuitable, decompress the target with -d. This replaces the wrapper and keeps the wrapper itself as TARGET~, so check which backup you actually want before doing anything else.
$ gzexe -d -- "$TARGET"
$ "$TARGET" --version
your-program 1.2.3
$ file "$TARGET"
/path/to/your/executable: ... executable
Once the restored file passes your baseline and its attributes are correct, remove only the now-unneeded wrapper backup, and only once you have identified it precisely. That removal is irreversible unless another copy exists.
$ stat -c '%A %a %U:%G %n' -- "$TARGET" "$TARGET~"
$ rm -- "$TARGET~"
$ test ! -e "$TARGET~" && echo 'wrapper backup removed'
If you compress the file again after restoring it, the meaning of TARGET~ changes again. Do not assume the suffix identifies the original forever.
/tmp for temporary work, but it still has to create the backup and replace the target. Fix directory permissions, or use elevated privileges, only after checking the exact path.PATH when execution fails with a decompression error. A restricted environment can hide gzip or mktemp.stat, then restore only the permissions or ownership the program actually needs.PATH.~ backup is kept for recovery, or removed only once a separate backup is confirmed.