tar Command in Linux: Complete Guide to Archive Creation, Extraction, and Parameters

tar command in Linux and it perimeters

If I had to pick the single command I’ve used more than any other across my years working on Linux systems, it would probably be tar. Backups, deployments, moving directory trees between servers, packaging source code releases — tar shows up everywhere. The name literally comes from “tape archive,” a callback to when its primary job was writing sequential archives to magnetic tape drives, but it’s just as central to modern workflows involving cloud storage, container images, and CI/CD pipelines.

Let me go through everything about tar — from basic syntax to the archive format internals and the workflows I actually use on production systems.

What tar Does

tar bundles multiple files and directories, along with their metadata (permissions, ownership, timestamps, symlinks), into a single archive file. On its own, tar doesn’t compress anything — it just concatenates data in a structured format. Compression is typically layered on top using gzip, bzip2, xz, or zstd, either as a separate step or via tar‘s built-in flags that pipe through those compressors automatically.

Basic Syntax

tar [options] [archive-file] [file-or-directory ...]

tar supports both the traditional single-dash style (tar -cvf) and, on GNU tar, a more modern long-option style (tar --create --verbose --file). Most admins, myself included, stick to the compact form out of habit.

The Core Operating Modes

Every tar invocation needs exactly one of these mode flags:

ModeMeaning
-cCreate a new archive
-xExtract files from an archive
-tList/table the contents of an archive without extracting
-rAppend files to the end of an existing archive
-uUpdate — append files newer than the copy already in the archive
-dCompare (diff) archive contents against the filesystem
-AAppend (concatenate) one tar archive to the end of another

Common Modifier Flags

FlagDescription
-f <file>Specify the archive filename (almost always required)
-vVerbose — print filenames as they’re processed
-zFilter through gzip (create/extract .tar.gz)
-jFilter through bzip2 (.tar.bz2)
-JFilter through xz (.tar.xz)
--zstdFilter through zstd (modern GNU tar)
-C <dir>Change to directory before performing the operation
--exclude=PATTERNSkip files matching a pattern
-pPreserve permissions exactly (important when run as root)
--numeric-ownerStore/restore numeric UID/GID rather than resolving names
-kKeep existing files during extraction; don’t overwrite
--strip-components=NRemove N leading path components on extraction

Practical Examples I Tested

Creating a basic archive:

$ mkdir -p tartest/subdir
$ echo "file1 content" > tartest/file1.txt
$ echo "file2 content" > tartest/subdir/file2.txt
$ tar -cvf archive.tar tartest/
tartest/
tartest/subdir/
tartest/subdir/file2.txt
tartest/file1.txt

Listing archive contents without extracting anything:

$ tar -tvf archive.tar
drwxr-xr-x root/root         0 2026-07-31 01:37 tartest/
drwxr-xr-x root/root         0 2026-07-31 01:37 tartest/subdir/
-rw-r--r-- root/root        14 2026-07-31 01:37 tartest/subdir/file2.txt
-rw-r--r-- root/root        14 2026-07-31 01:37 tartest/file1.txt

Creating a compressed archive in one step:

$ tar -czvf archive.tar.gz tartest/
tartest/
tartest/subdir/
tartest/subdir/file2.txt
tartest/file1.txt
$ ls -la archive.tar archive.tar.gz
-rw-r--r-- 1 root root 10240 archive.tar
-rw-r--r-- 1 root root   202 archive.tar.gz

Extracting into a specific target directory:

$ mkdir extracted
$ tar -xvf archive.tar -C extracted
$ find extracted -type f
extracted/tartest/subdir/file2.txt
extracted/tartest/file1.txt

Excluding files matching a pattern while archiving:

$ tar -cvf archive2.tar --exclude='*.gz' tartest/
tartest/
tartest/subdir/
tartest/subdir/file2.txt
tartest/file1.txt

How tar Works Internally

The tar format is deceptively simple: it’s a sequence of 512-byte blocks. Each file stored in the archive is preceded by a 512-byte header block describing its name, size, permissions, ownership, modification time, and type (regular file, directory, symlink, etc.), followed by the file’s data padded out to a multiple of 512 bytes. The archive ends with two consecutive all-zero blocks marking EOF.

This block-based design is a direct legacy of tape drives, which read and wrote data in fixed-size blocks efficiently, but it also means tar archives can be streamed — you can create or read a tar archive without needing to seek, which is why piping tar through ssh, nc, or a compressor works so naturally:

tar -czf - /data | ssh user@remote 'cat > backup.tar.gz'

There are actually multiple tar header formats in circulation — the original V7 format, POSIX ustar, GNU’s own extensions (for long filenames beyond ustar’s limits), and PAX (an extended POSIX format that supports very long filenames and extra metadata like extended attributes). GNU tar automatically chooses appropriate extensions when a filename or metadata field won’t fit in the classic 100-character ustar limit.

When -z, -j, -J, or --zstd is used, tar doesn’t do the compression itself — it pipes the entire tar byte stream through the corresponding compressor program (gzip, bzip2, xz, zstd) as a subprocess, then writes the compressed output to the destination. This is why you can’t efficiently “list one file” out of a huge .tar.gz without decompressing everything up to that point — random access isn’t possible through a compression filter, unlike with formats like zip that compress each file independently.

Real-World Use Cases

Full system or directory backups:

tar -czpf /backup/etc-$(date +%Y%m%d).tar.gz --numeric-owner /etc

I always include -p (preserve permissions) and --numeric-owner for backups, so restoring on a different machine — or the same machine after a reinstall — doesn’t silently remap ownership based on username-to-UID differences.

Deploying application code to a server without needing intermediate storage:

tar -czf - -C /local/build . | ssh deploy@server 'tar -xzf - -C /var/www/app'

Excluding noisy directories like .git or node_modules when archiving a project:

tar --exclude='.git' --exclude='node_modules' -czf project.tar.gz myproject/

Incremental backups using GNU tar’s snapshot feature:

tar --create --file=full.tar --listed-incremental=snapshot.snar /data
# later, only changed files since the snapshot:
tar --create --file=incremental.tar --listed-incremental=snapshot.snar /data

This is genuinely one of GNU tar’s more powerful, underused features — it tracks a snapshot file that records what’s already been backed up, letting subsequent runs capture only changes.

tar vs cpio vs zip

I get asked which archiving tool to use fairly often:

  • tar is the default for Unix/Linux backups and source distributions; it preserves Unix permissions and ownership faithfully and streams well.
  • cpio predates tar’s widespread dominance and is still used internally by RPM packages and some initramfs images, but it’s rarely chosen for new general-purpose archiving.
  • zip stores each file compressed independently, enabling random access to individual files without decompressing the whole archive, and it’s the better choice for cross-platform compatibility with Windows and macOS users — but it historically handles Unix permissions and symlinks less consistently than tar.

Troubleshooting Common Problems

“tar: Cannot connect to A: resolve failed” or similar — often means you accidentally invoked the old-style tar syntax where the first non-flag argument was misinterpreted as part of a remote-tape spec (user@host:file). Double-check your flag ordering, especially with -f.

“Not enough space” mid-extraction — verify the destination filesystem free space with df -h before extracting large archives; tar doesn’t pre-check available space.

Permission errors extracting as a non-root user — if the archive contains files owned by root or other users, extracting as a regular user will silently change ownership to the current user (unless you have CAP_CHOWN privileges). Compare tar -tvf output against your actual UID/GID expectations before assuming a clean restore.

Corrupted or truncated archives — verify integrity before trusting a backup:

tar -tzf archive.tar.gz > /dev/null && echo "archive OK"

If this exits non-zero, the archive is likely damaged.

Performance Optimization

For very large archives, the compressor you choose matters far more than tar itself. gzip is fast but has mediocre compression; xz compresses noticeably smaller but is much slower, especially at high levels; zstd offers a strong balance and, critically, supports multi-threaded compression with -T0:

tar --use-compress-program='zstd -T0 -19' -cf archive.tar.zst /data

I use this pattern on multi-core servers whenever I need both strong compression and reasonable speed, since single-threaded xz -9 on a large dataset can take hours where multi-threaded zstd finishes in minutes.

Security Implications

Extracting an untrusted tar archive is a classic vector for path traversal attacks — a maliciously crafted archive entry named something like ../../etc/passwd could overwrite files outside your intended extraction directory. GNU tar defends against this by default (rejecting absolute paths and .. components unless you explicitly pass -P/--absolute-names), but it’s still worth extracting anything from an untrusted source inside an isolated directory or container rather than as root in a sensitive location.

Compatibility Across Distributions

GNU tar is the default on virtually every Linux distribution — Debian, Ubuntu, RHEL, Fedora, Arch, openSUSE — so behavior is highly consistent. The main compatibility wrinkle comes up when exchanging archives with BSD tar (the default on macOS and FreeBSD), which handles some GNU-specific extensions (like sparse file support or certain extended attributes) differently. For archives meant to be portable across systems, sticking to the POSIX/PAX format (tar --format=pax) avoids most cross-implementation surprises.

Verifying Archives and Comparing Against the Filesystem

Beyond basic listing, GNU tar’s diff/compare mode (-d) lets you check whether an archive still matches what’s currently on disk, without extracting anything:

$ tar -df archive.tar

If nothing prints, the archive matches the current filesystem state exactly. Any mismatches (changed permissions, modified content, missing files) get reported line by line. I use this after restoring a backup to a staging area, confirming the extraction was faithful before promoting it to production, and also periodically against long-term archival backups to catch silent bit rot or accidental modification of “read-only” backup files.

Working With Multi-Volume Archives

For archives too large to fit on a single piece of removable media (a genuine concern in the tape era, and still occasionally relevant for physical media transfers today), tar supports splitting across multiple volumes:

tar -cM -L 1000000 -f volume1.tar /data

The -M flag enables multi-volume mode, and -L sets the size limit per volume in kilobytes. Tar will prompt you to insert or specify the next volume file as each fills up. I’ve used this exactly once in recent memory — moving a large dataset onto several separate encrypted USB drives for physical offsite transport, where splitting was the only practical option.

Preserving Extended Attributes and ACLs

Standard tar headers don’t capture Linux extended attributes (xattrs) or POSIX ACLs by default, which matters if your files rely on SELinux contexts, capabilities, or fine-grained ACL permissions. GNU tar supports these explicitly:

tar --acls --xattrs -cvpf archive.tar /secure-data

I make a point of adding these flags for any backup involving SELinux-labeled systems or directories using ACLs beyond standard Unix permissions — without them, a restore can silently lose security context information that’s easy to overlook until something mysteriously stops working after a restore, like a service failing to start because its files lost their expected SELinux label.

Automating Rotating Backups With tar and find

A pattern I use on several personal and small-business servers combines tar with find-based retention cleanup, structured as a small, dependency-free backup script:

#!/bin/bash
set -euo pipefail

SRC=/var/www
DEST=/backups
DATE=$(date +%Y%m%d-%H%M)
KEEP_DAYS=14

tar --exclude='cache' --exclude='tmp' -czpf "$DEST/www-$DATE.tar.gz" "$SRC"
find "$DEST" -name "www-*.tar.gz" -mtime "+$KEEP_DAYS" -delete

echo "Backup complete: www-$DATE.tar.gz"

Simple, but genuinely reliable — I’ve had scripts like this running unattended via cron for years without issues, precisely because tar’s behavior is so stable and well-understood across updates.

Restoring Only Specific Files From a Large Archive

You don’t need to extract an entire archive just to pull out one or two files. Tar accepts specific paths as extraction filters:

tar -xvf archive.tar tartest/subdir/file2.txt

This extracts only the named file (or directory subtree), leaving the rest of the archive’s contents untouched on disk — a detail that’s saved me significant time restoring a single accidentally-deleted config file from a much larger nightly backup archive, rather than extracting gigabytes of unrelated data just to get at one file.

Summary

tar is one of those tools where the basic usage takes five minutes to learn, but understanding the block-based format, the way compression is layered on as an external filter, and features like incremental snapshots pays off constantly in real system administration work. Whether I’m shipping a deployment over SSH, backing up /etc, or unpacking a decades-old source tarball, tar’s simplicity and near-universal availability are exactly why it’s stayed indispensable for as long as it has.

References

  • GNU Tar Manual: https://www.gnu.org/software/tar/manual/tar.html
  • man tar
  • POSIX ustar format specification: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html
  • GNU Tar incremental backups documentation: https://www.gnu.org/software/tar/manual/html_node/Incremental-Dumps.html
Total
0
Shares

Leave a Reply

Previous Post
gzip command in Linux and it perimeters

gzip Command in Linux: Complete Guide to File Compression and Parameters

Next Post
uncompress command in Linux and it perimeters

uncompress Command in Linux: Complete Guide to Decompressing Z Files and Parameters

Related Posts