Payments are experiencing issues due to temporary restrictions in Russia. If your payment does not go through, please submit a support request.Our support team is available 24/7 — we are always here to help with hosting and server issues.We are now accepting requests for dedicated server rental and colocation services in our data center.Reminder: we recommend enabling backups for additional data protection.A new VPS/VDS lineup with NVMe storage and improved performance is now available.Maintenance work on some servers has been completed. All services are operating normally.
Article7 min readViews2

tar --compare: How to Verify an Archive Against the Source Directory Before Cleanup

Reproducible GNU tar 1.35 verification: compare an archive with a directory without unpacking over data, distinguish exit codes 0, 1, and 2, and highlight a critical boundary—the command does not notice extra files.

Comments 0

Archive cartridge and reference folders under violet inspection light in a bright room
In this article

tar --compare answers a narrow question: do the archive members match the files in the directory from which the copy was made? The command does not unpack the archive over the original data. Exit code 0 means no differences were found among archive members; code 1 means differences exist; code 2 means the check ended with an error.

An archive member is a record inside tar containing a path and metadata. File correspondence is an object with the same path in the selected directory. This is important: the command starts with the archive contents, not by searching for everything lying nearby on the disk.

First, let us check the boundaries. Verification is useful immediately after creating the archive while the source directory is still fixed and not yet cleaned. For a live site, the result quickly becomes outdated: the application may modify a file even after the snapshot. Therefore, the source directory must be an immutable prepared copy, a snapshot, or a stopped test model, not a live directory with active writes.

Input conditions

  • Linux with GNU tar; the check below was performed on GNU tar 1.35.

  • The backup.tar archive and the source directory, both corresponding to the same point in time.

  • Read permissions for the archive and all files being compared.

  • Isolated temporary directory: the example commands do not access the live site or the network.

tar --version

tar (GNU tar) 1.35

In the test from October 24, 2026, two short text files were used: site/index.html and db/catalog.sql. These are sample data, not a copy of a client or production database.

Preparing a secure staging environment

lab_dir="$(mktemp -d)"

printf '%s\n' "$lab_dir"

mkdir -p -- "$lab_dir/source/site" "$lab_dir/source/db"

printf '%s\n' 'version=A' > "$lab_dir/source/site/index.html"

printf '%s\n' 'rows=42' > "$lab_dir/source/db/catalog.sql"

find "$lab_dir/source" -type f -exec touch -d '2026-10-24 00:00:00 UTC' {} +

tar --create --file="$lab_dir/backup.tar" --directory="$lab_dir/source" .

The lab_dir variable is defined by the first command. All subsequent write operations are limited to the mktemp directory created. File dates are recorded solely for reproducibility of the comparison; they are not a recommendation for production copies.

First comparison: archive and directory match

cp -a -- "$lab_dir/source" "$lab_dir/match"

tar --compare --file="$lab_dir/backup.tar" --directory="$lab_dir/match"

printf 'rc=%s\n' "$?"

rc=0

Empty output with exit code 0 means GNU tar found no differences between the contents of backup.tar and their corresponding files in match. Empty output without a saved exit code is insufficient: automation must verify both conditions.

Changing one byte while keeping size and time unchanged

cp -a -- "$lab_dir/source" "$lab_dir/changed"

printf 'B' | dd of="$lab_dir/changed/site/index.html" bs=1 seek=8 conv=notrunc status=none

touch -r "$lab_dir/source/site/index.html" "$lab_dir/changed/site/index.html"

tar --compare --file="$lab_dir/backup.tar" --directory="$lab_dir/changed"

./site/index.html: Contents differ

The command exited with code 1. The file size and mtime were preserved, but GNU tar read the content and detected a replacement of A with B. This is a useful distinction from checking only name, size, and time.

Missing file and changed permissions

For the missing-file scenario, the file is not permanently deleted: it is moved outside the compared directory but remains within the temporary staging environment.

cp -a -- "$lab_dir/source" "$lab_dir/missing"

mv -- "$lab_dir/missing/db/catalog.sql" "$lab_dir/catalog.sql.off"

tar --compare --file="$lab_dir/backup.tar" --directory="$lab_dir/missing"

tar: ./db/catalog.sql: Warning: Cannot stat: No such file or directory

Result: code 1 — archive member not found in the directory. In a separate scenario, chmod 0600 for site/index.html with an initial 0644 produced the "Mode differs" message and the same code 1. Therefore, the comparison covers not only content but also metadata stored in the archive.

The catch: an extra file goes unnoticed

cp -a -- "$lab_dir/source" "$lab_dir/extra"

printf '%s\n' 'not in archive' > "$lab_dir/extra/unlisted.txt"

tar --compare --file="$lab_dir/backup.tar" --directory="$lab_dir/extra"

printf 'rc=%s\n' "$?"

rc=0

tar proceeds from archive members to the file system. Therefore, unlisted.txt, which is not in backup.tar, is not included in the comparison and does not change the code. Code 0 does not prove that the archive contains everything currently in the directory. Completeness of the contents must be checked separately against an expected list or file snapshot.

TAR members are matched to two file system paths, while unlisted.txt remains outside the comparison scope.
GNU tar matches archive members with file system paths. unlisted.txt has no corresponding member in the archive, so --compare does not check it.

Script

Observation

Code

Output

Exact match

output is empty

0

no differences among archive members found

One byte changed

Contents differ

1

contents differ

File not found

Cannot stat

1

archive member not found

Mode 0644 → 0600

Mode differs

1

metadata differs

An extra file exists in the catalog

the output is empty

0

the extra file is outside the verification scope

Five outcomes of tar --compare: match, modified byte, missing file, modified mode, and extra file, with codes 0 and 1.
Five outcomes of the GNU tar 1.35 test. Code 0 means only that there are no differences among archive members; an extra file on the disk remains outside the check scope.

How to read exit codes

The official GNU tar manual describes --compare / --diff as comparing archive members with the file system and lists the attributes checked. In the section on exit codes, code 1 indicates found differences with --compare, and code 2 indicates a fatal error.

For a separate check of a fatal error in the same staging environment, an archive that does not exist is specified:

tar --compare --file="$lab_dir/no-such.tar" --directory="$lab_dir/match"

printf 'rc=%s\n' "$?"

rc=2

Code 2 here does not mean a missing file difference, but the inability to perform the check: the archive cannot be opened. In automation, this status must be distinguished from RC 1.

Do not merge 1 and 2 into a single status of 'corrupted archive'. Code 1 may reflect an expected change in the directory after the snapshot. Code 2 means the check operation itself did not complete normally: for example, the archive is unavailable or unreadable.

Safe cleanup of the training environment

First, output the path and verify it refers to a temporary directory. The cleanup below is allowed only if the path matches a directory created by mktemp based on a template in TMPDIR or /tmp; for any other path, the command stops.

case "$lab_dir" in "${TMPDIR:-/tmp}"/tmp.*) rm -rf -- "$lab_dir" ;; *) printf 'cleanup stopped: %s\n' "$lab_dir" >&2 ;; esac

Where this check fits into backup acceptance testing

  1. Immediately after creating the archive, record the original file tree or snapshot and the GNU tar version.

  2. Run tar --compare and save the full output along with the exit code.

  3. For exit code 1, distinguish between content differences, missing files, and metadata differences; do not infer the cause from a single line of output.

  4. Separately compare the expected composition, as the command does not search for extra files in the source tree.

  5. After a successful comparison, verify the integrity of the submitted archive and perform a test restoration in isolation.

If the source directory no longer exists, tar.gz pre-extraction check addresses a different question: can the gzip stream and tar structure be read? SHA-256 manifest helps detect changes to already saved files. Neither of these checks replaces application restoration.

Result boundaries

  • Comparison does not prove archive completeness relative to business requirements.

  • The command does not confirm the consistency of a dump from a running database.

  • An extra file in a directory that is not in the archive does not make the result non-zero.

  • A working directory with ongoing writes may produce differences that arose after the copy was created.

  • The check does not confirm the archive's authenticity and does not replace a protected manifest or signature.

  • Results and wording apply to GNU tar 1.35; output may differ in another implementation or version.

Readiness criterion: tar --compare completed with code 0 on the directory of the same point in time, the expected composition was verified separately, and the output and tool version were saved. Only after this is it meaningful to proceed to transfer verification and test restoration.

Discussion 0

Share your experience and ask questions. Comments without links appear after editorial review.

No comments yet. Start the discussion.