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.
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"
.tar.gz suffix is two facts. .tar is the archive format; .gz is gzip compression.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")"
--create selects archive creation.--gzip sends the archive through gzip.--file names the output.--directory is order-sensitive. It changes directory before the following source name is processed. That avoids recording an absolute path, so the archive unpacks as project/... rather than embedding your full home-directory path.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"
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.
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.
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
--diff means files differ.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.
tar --extract --gzip --file="$archive" --directory="$destination" project/readme.txt.--strip-components=1 does it, but review the resulting paths first: it changes where every selected member lands.--exclude='project/.cache'. Exclusion patterns are glob-style and path matching can surprise you, so list the result afterwards.--directory casually mid-command. It affects the options and file names that follow it, not necessarily everything on the line.--add-file=./-notes when creating an archive, or the name can be read as a tar option.--append is not for compressed archives. It changes an existing uncompressed archive only.--update does not replace. It appends newer files, so one archive can hold several versions of the same name. For a clean, predictable backup, create a new archive instead of relying on either operation.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.
tar --list was reviewed and showed only expected member paths.tar --diff returned 0, or any difference was investigated and kept for recovery.