Compare an Extracted Tree with Its Tar Archive Using ptardiff

ptardiff compares an extracted directory against the tar archive it came from and can save the differences as a patch. That last part needs an optional Perl dependency, which is not always installed. Allow about fifteen minutes. You need Perl, a tar archive, a writable working directory and a copy of the archive extracted without changing its paths.

This guide describes the installed ptardiff from the Debian perl package, version 5.38.2-3.2ubuntu0.6. On this machine, Archive::Tar is present but Text::Diff is not, so the comparison command stops before producing a diff. That is a useful pre-flight result, not a reason to make the archive or extracted files writable by root.

1. Check the installed command

Confirm which executable and Perl package you are using. These are ordinary, read-only commands and do not need elevated privileges:

$ command -v ptardiff
/usr/bin/ptardiff
$ dpkg-query -W -f='${Package} ${Version}\n' perl
perl 5.38.2-3.2ubuntu0.6
$ perl -MArchive::Tar -e 'print "$Archive::Tar::VERSION\n"'
2.40

Ask for the short help text before preparing any files:

$ ptardiff -h

Usage:  ptardiff ARCHIVE_FILE
        ptardiff -h

The installed program exits non-zero after printing this usage text. That is how this version implements its help path. The documented comparison form has one argument: the archive file.

2. Extract the archive into a test tree

Work in a disposable copy or a version-controlled checkout. Do not extract an untrusted archive into a directory containing important files. Archive extraction can create or replace paths, and the result is part of the input to the comparison.

$ mkdir -p /path/to/ptardiff-work
$ cd /path/to/ptardiff-work
$ tar -xzf /path/to/PROJECT-VERSION.tar.gz
$ test -d PROJECT-VERSION && echo 'extracted tree is ready'
extracted tree is ready

The example assumes a gzip-compressed tar archive. Use the extraction command appropriate to the archive you actually have, and keep the archive outside the extracted tree. The top-level directory matters: ptardiff looks up each archive member by its stored path relative to the current working directory.

Checkpoint: list one known member in both places. A missing or differently named path will look like a deletion or an addition rather than the edit you intended to inspect:

$ tar -tzf /path/to/PROJECT-VERSION.tar.gz | head
PROJECT-VERSION/
PROJECT-VERSION/README
$ test -f PROJECT-VERSION/README && echo 'working copy matches archive layout'
working copy matches archive layout

3. Make and inspect a controlled edit

Edit a file below the extracted directory with your normal editor. For a harmless test, append a clearly temporary line, then inspect the result:

$ printf '%s\n' 'local review change' >> PROJECT-VERSION/README
$ tail -n 3 PROJECT-VERSION/README
local review change

This changes only the extracted copy, not the archive. If you need to undo the example before comparing, remove that exact line with your editor or restore the extracted directory from a fresh extraction. Do not use a broad recursive removal command against a path you have not checked.

4. Run ptardiff and capture its patch

Run the command from the directory that contains the extracted top-level path. Redirect standard output to a new file so the terminal stays readable:

$ ptardiff /path/to/PROJECT-VERSION.tar.gz > review.patch
$ status=$?
$ printf 'ptardiff status: %s\n' "$status"
ptardiff status: 0

When it works, the command reads every regular file in the archive, finds the same path in the current directory and sends the differences to standard output. The patch may contain several files. It is not a command to update the archive, and it does not modify the extracted files.

Do not treat an empty patch as proof that the whole tree is identical. The program only visits regular files that are listed in the archive. Check the output file and the paths in it:

$ test -s review.patch && echo 'differences captured'
$ sed -n '1,40p' review.patch

On this host the command instead reports:

$ ptardiff /path/to/PROJECT-VERSION.tar.gz > review.patch
 This tool requires the 'Text::Diff' module to be installed

That error is expected here because the optional module is missing. The shell still creates review.patch, but it is empty. Check the exit status before using it, and delete or ignore that empty file rather than presenting it as a valid review. Installing the module is a package-management decision for the machine owner; it is not part of this read-only workflow and normally requires elevated privileges.

5. Diagnose path and archive mistakes

If the dependency is installed but the result is unexpected, first confirm the current directory and archive members:

$ pwd
$ tar -tzf /path/to/PROJECT-VERSION.tar.gz | sed -n '1,20p'
$ find PROJECT-VERSION -maxdepth 2 -type f -print

A common trap is extracting with a different directory prefix, such as removing the archive's top-level directory before running ptardiff. The tool passes each stored member name to its diff routine, so the current working tree must expose those names. Another trap is editing a file that is not in the archive. Such a file is outside the comparison.

Keep the archive unchanged while investigating. If the archive itself is damaged or unreadable, test it separately with tar -tzf /path/to/PROJECT-VERSION.tar.gz. If the list is correct but ptardiff still reports the dependency error, stop there and arrange for Text::Diff to be installed through your normal package or Perl module process. Do not copy a module into a random directory or run the comparison as root to bypass a missing dependency.

Done means