Create and safely unpack archives with GNU tar

One careless tar extraction can scatter files across your home directory or quietly overwrite the ones you needed. In about 15 minutes you will create a compressed archive, check what is inside, unpack it somewhere safe and prove the copy matches.

The examples use GNU tar 1.35 from the tar package. You need:

Use sudo only when the source or destination genuinely belongs to another user or is a protected system location.

1. Pick the archive and source

Set the two paths, then look at the source before you archive it.

source_dir="$HOME/project"
archive="$HOME/project-2026-09-27.tar.gz"
test -d "$source_dir" && printf 'Source: %s\n' "$source_dir"
du -sh "$source_dir"

2. Create a compressed archive

Create it from the parent directory so every member has a predictable top-level name.

tar --create --gzip --file="$archive" \
  --directory="$(dirname -- "$source_dir")" \
  "$(basename -- "$source_dir")"

Tip: For another compressor, match the option to the suffix: --bzip2 for .bz2, --xz for .xz, or --zstd for .zst, provided the program is installed. The installed man page also documents --auto-compress, which picks compression from the suffix. Never combine several compression options.

Check the output exists and is not empty:

test -s "$archive" && ls -lh -- "$archive"

3. Inspect before you extract

Listing writes nothing to disk. Extraction is the step that changes things, so look first.

tar --list --gzip --file="$archive"

Checkpoint: You should see names such as project/ and project/readme.txt.

Treat this list as a safety review. Look for:

For a large archive, save the list instead of scrolling past it:

tar --list --gzip --file="$archive" > /tmp/project-tar-members.txt
sed -n '1,40p' /tmp/project-tar-members.txt

Warning: An archive from an untrusted source is not safe just because it lists neatly. Tar can contain symbolic links, hard links and special files. Extract unknown archives into a new directory as an ordinary user, never into /, a home directory holding live data, or a service's working directory.

4. Extract into an empty destination

Only once the member list looks right, create a destination and unpack into it.

destination="$HOME/tmp/project-unpacked"
mkdir -p -- "$destination"
tar --extract --gzip --file="$archive" --directory="$destination"
find "$destination" -maxdepth 3 -type f -print

Tar normally extracts as the current user. Run it as root and GNU tar's defaults change: the superuser may restore recorded ownership and permissions. Prefer a non-privileged destination. If you must use sudo, inspect first and name the destination explicitly:

sudo tar --extract --gzip --file="$archive" --directory="/srv/example"

Warning: That command changes files under /srv/example. Stop if the directory holds files that must not be replaced. Add --keep-old-files to avoid overwriting: tar then reports an error for any member whose destination already exists.

Recovery: Tar has no general undo. If extraction created an unwanted directory, check its path carefully and remove only that directory, with a file manager or a reviewed command.

5. Verify the result

Compare the archive members with the extracted files:

tar --diff --gzip --file="$archive" --directory="$destination" project

Checkpoint: A clean comparison normally prints nothing and exits with status 0.

In a script, check the status straight away:

if tar --diff --gzip --file="$archive" --directory="$destination" project; then
  printf '%s\n' 'Archive and extracted files match.'
else
  status=$?
  printf 'tar comparison failed with status %s\n' "$status" >&2
  exit "$status"
fi

Recovery: If files differ, do not delete the destination straight away. Keep it for inspection, compare timestamps and permissions, and extract again into a fresh directory if you need a clean retry.

Common traps

Tip: The local tar(1) page is the authority for the GNU tar 1.35 behaviour used here. For the full reference, see the GNU Tar manual.

Done means