Compare bzip2 Archives with bzdiff and bzcmp
bzdiff and bzcmp let you diff two bzip2 archives, or an archive against a plain file, without unpacking either one first. You get a clear result: 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: no sudo, no change to your source files, no change to services or configuration.
1. Check the installed commands
Confirm 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. What matters is the program version, because this is a small shell wrapper around diff or cmp, and distributions 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
Silence means 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 what changed. A difference is a normal comparison result, not a command failure: diff returns 1 when the files differ and 0 when they match.
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, so you can 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
Those temporary names in the output are expected: the manpage calls this out as a limitation. Messages from diff or cmp can refer to a temporary file rather than the names you supplied. The wrapper removes that temporary file once the comparison finishes.
Keep the compressed originals until you have inspected an important result. This command is read-only towards those inputs, but a comparison only tells you their decompressed contents differ or match; it does not prove either archive is the file you expected.
4. Use the paired-file shortcut
With one argument, bzdiff applies a specific naming convention. Pass /work/report.txt and it compares that uncompressed file with /work/report.txt.bz2:
$ bzdiff -u /work/report.txt
$ printf '%s\n' "$?"
0
Handy when an archive and its extracted counterpart sit beside each other. The suffix is not guessed from an arbitrary compressed pathname the way some archive tools guess names: 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' "$?"
Status 0 means both files were readable. If either path is absent or unreadable, fix the path or the permissions through your normal process. Do not grant broad permissions or run the whole comparison as root just to paper over a path mistake.
5. Choose bzcmp for byte-oriented comparison
bzcmp handles compressed files the same way but invokes cmp instead of diff. Reach for 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 pass straight through to cmp or diff, so check those manpages before putting a less common option into a script: the wrapper does not translate a bzdiff option into a bzcmp one.
6. Put the result in a script
Branch on the exit status instead of parsing the output. This 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 it suppresses the normal difference listing. If your script must work across several platforms, verify diff -q locally first. A non-zero result is not automatic proof of changed content either: a missing file, an unreadable input, invalid bzip2 data, or a downstream tool error all need investigating.
Common traps
- Do not unpack first out of habit. 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.
- Watch where you redirect. bzdiff writes differences to standard output, so
> result.patchis safe whenresult.patchis a new destination, but shell redirection truncates an existing destination before bzdiff even starts. Choose a new name or copy the old result first. - Exit status is not a monitoring alarm. The wrapper preserves the exit status from
difforcmp. 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.
Recovery
If a report was accidentally truncated by a redirect, stop writing to it and restore it from your backup or version control; there is no undo operation in bzdiff.
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 shortcut, matching
fileagainstfile.bz2. - 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.