Compare bzip2 Files Safely with bzdiff and bzcmp
You will compare bzip2-compressed files without unpacking them into your working directory, and you will know whether the files are identical, different, or could not be checked. The examples use bzdiff and bzcmp from bzip2 1.0.8, installed here as Ubuntu package version 1.0.8-5.1ubuntu0.1.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about ten minutes. You need a shell, two readable files, and the bzip2 package. These commands read inputs and create only the compressed examples used for testing. They do not need sudo, do not alter the source files, and do not change services or configuration.
1. Check the installed commands
Confirm that the wrappers are available and record the compressor version:
$ command -v bzdiff
/home/linuxbrew/.linuxbrew/bin/bzdiff
$ command -v bzcmp
/home/linuxbrew/.linuxbrew/bin/bzcmp
$ bzip2 --version
bzip2, a block-sorting file compressor. Version 1.0.8, 13-Jul-2019.
The pathname can differ on your machine. The important detail is the program version, because this is a small shell wrapper around diff or cmp, and distributions can carry their own packaging changes. Read the installed bzdiff(1) page when a local version differs.
Checkpoint
Both commands resolve, and bzip2 --version reports the version you intend to document or automate against.
2. Compare two ordinary files
With two arguments, bzdiff accepts compressed or uncompressed files in any combination. Start with two uncompressed files:
$ bzdiff /path/to/old.txt /path/to/new.txt
There is no output when the files match, and the command returns status 0. For a readable line-by-line result, pass an option understood by diff:
$ bzdiff -u /path/to/old.txt /path/to/new.txt
--- /path/to/old.txt 2026-09-22 16:00:00.000000000 +0100
+++ /path/to/new.txt 2026-09-22 16:01:00.000000000 +0100
@@ -1,2 +1,2 @@
alpha
-beta
+gamma
The timestamps and context can differ. The leading minus and plus lines show the changed content. A difference is a normal comparison result, not a command failure: diff returns 1 when the files differ and 0 when they are the same.
Checkpoint
Run printf '%s\n' "$?" immediately after the comparison. Do not run another command first, because that replaces the status you are checking.
3. Compare compressed files directly
The wrapper decompresses inputs as needed and feeds the resulting text to diff. You can therefore compare two .bz2 files without making permanent uncompressed copies:
$ bzdiff -u /archive/old.txt.bz2 /archive/new.txt.bz2
--- - 2026-09-22 16:27:16.633465530 +0100
+++ /tmp/bzdiff.NrCp3IOfRY 2026-09-22 16:27:16.591432331 +0100
@@ -1,2 +1,2 @@
alpha
-beta
+gamma
$ printf '%s\n' "$?"
1
Temporary names in the output are expected. The manpage calls this out as a limitation: messages from diff or cmp can refer to temporary files rather than the names you supplied. The temporary file is used for the comparison and is removed by the wrapper after the comparison finishes.
Keep the compressed originals until you have inspected an important result. This command is read-only with respect to those inputs, but a comparison still tells you only that their decompressed contents differ or match. It does not prove that either archive is the expected file.
4. Use the paired-file shortcut
With one argument, bzdiff applies a specific naming convention. If you pass /work/report.txt, it compares that uncompressed file with /work/report.txt.bz2:
$ bzdiff -u /work/report.txt
$ printf '%s\n' "$?"
0
This is useful when an archive and its extracted counterpart sit beside each other. The suffix is not guessed from an arbitrary compressed pathname in the way some archive tools guess names. For this shortcut, give the base, uncompressed name and make sure the matching .bz2 file exists.
A missing pair is an input error. Check both paths without changing anything:
$ ls -l /work/report.txt /work/report.txt.bz2
$ test -r /work/report.txt && test -r /work/report.txt.bz2
$ printf '%s\n' "$?"
If the final status is 0, both files were readable. If either path is absent or unreadable, correct the path or permissions through your normal process. Do not grant broad permissions or run the whole comparison as root just to hide a path mistake.
5. Choose bzcmp for byte-oriented comparison
bzcmp has the same compressed-file handling but invokes cmp instead of diff. Use it when you want a compact equality test or byte and character positions rather than a patch-like view:
$ bzcmp /archive/old.txt.bz2 /archive/new.txt.bz2
/archive/old.txt.bz2 /archive/new.txt.bz2 differ: byte 7, line 2
$ printf '%s\n' "$?"
1
The exact diagnostic depends on the installed cmp. As with bzdiff, status 0 means equal and status 1 means different. Options are passed directly to cmp or diff, so check those tools' manpages before putting a less common option into a script. The wrapper does not translate a bzdiff option into a bzcmp option.
6. Put the result in a script
Branch on the exit status instead of parsing the output. This example treats a difference as an intentional result, while reporting an input or decompression problem separately:
if bzdiff -q /path/to/old.txt.bz2 /path/to/new.txt.bz2; then
printf '%s\n' 'files match'
else
status=$?
if [ "$status" -eq 1 ]; then
printf '%s\n' 'files differ'
else
printf 'comparison failed with status %s\n' "$status" >&2
exit "$status"
fi
fi
-q is a diff option on systems where the installed diff supports it, and suppresses the normal difference listing. If your script must work across several platforms, verify diff -q locally first. A non-zero result is not automatically proof of changed content: a missing file, unreadable input, invalid bzip2 data, or a downstream tool error also needs investigation.
7. Avoid the common traps
Do not unpack files first merely because a comparison tool is needed. That creates extra data and can leave stale extracted copies that someone later mistakes for current content. Use bzdiff or bzcmp for the comparison, and write an extracted file only when a later tool genuinely needs one.
Do not redirect a comparison into a source archive or into a useful report. bzdiff writes differences to standard output, so > result.patch is safe when result.patch is a new destination, but shell redirection truncates an existing destination before bzdiff starts. Choose a new name or copy the old result first. If a report was accidentally truncated, stop writing to it and restore it from your backup or version control; there is no undo operation in bzdiff.
Finally, remember that the wrapper preserves the exit status from diff or cmp. A monitoring check that treats every non-zero status as an outage will misreport ordinary differences. Capture the status immediately and decide whether status 1 is expected for your workflow.
Done means
- You confirmed the local bzip2 version and found both wrapper commands.
- You compared compressed and uncompressed inputs without changing the originals.
- You used
-uwith bzdiff for a readable unified diff, or bzcmp for a compact comparison. - You understand the one-argument
fileandfile.bz2naming convention. - Your script distinguishes an ordinary difference from an input or decompression failure.
- You chose output names carefully and have a recovery path for any redirected report.