Home / Alt manpages / tar(1)

  • tar(1)
  • User command
  • linux

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:

  • A shell. Nothing fancy.
  • A directory you can read. Ordinary files under your home directory need no elevated privileges.
  • Enough free space for both the archive and its extraction.

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"
  • The .tar.gz suffix is two facts. .tar is the archive format; .gz is gzip compression.
  • Tar will not guess the source. It does not infer a directory from the archive name, so keep the input path explicit.
  • Quote the variables. That protects spaces and shell metacharacters in a path.

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")"
  • --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"

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:

  • Absolute paths you did not expect.
  • Parent-directory components such as ../.
  • Device nodes.
  • Anything that would overwrite valuable data.

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
  • Status 1 from --diff means files differ.
  • Status 2 means a fatal error.
  • Other non-zero statuses can come from an external compressor.

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

  • Extract one member. Put its exact name after the archive options: tar --extract --gzip --file="$archive" --directory="$destination" project/readme.txt.
  • Strip leading path components. --strip-components=1 does it, but review the resulting paths first: it changes where every selected member lands.
  • Skip build output or caches. Use a checked glob such as --exclude='project/.cache'. Exclusion patterns are glob-style and path matching can surprise you, so list the result afterwards.
  • Do not drop --directory casually mid-command. It affects the options and file names that follow it, not necessarily everything on the line.
  • Filenames starting with a dash. Use --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.

Done means

  • The archive exists and uses the compression you intended.
  • tar --list was reviewed and showed only expected member paths.
  • Extraction went to a deliberate destination, without unnecessary privileges.
  • tar --diff returned 0, or any difference was investigated and kept for recovery.