💻 tar Quick Reference

tar cheat sheet / survival guide

Video: tar (Command Line Tips video)
Prefer to watch? This short video runs this page's main commands on a real Ubuntu 24.04 machine, with on-screen captions and no voiceover. Click to play, or watch it on YouTube.
tar [options] [ARCHIVE] [FILE...]
tar -czf backup.tar.gz ./project

tar bundles many files into one archive (a "tarball"). It only bundles;
compression (gzip, bzip2, xz, zstd) is a flag on top.

The three modes (pick exactly one)

-c    Create a new archive
-x    Extract files from an archive
-t    List the contents of an archive
-r    Append files to an existing (uncompressed) archive
-u    Append only files newer than the archive copy
-d    Compare the archive with the filesystem (also --diff)

Common flags

-f FILE   Archive file name (must come right after the flags, e.g. -czf name)
-v        Verbose: list files as they are processed
-z        gzip compression        (.tar.gz, .tgz)
-j        bzip2 compression       (.tar.bz2, .tbz2)
-J        xz compression          (.tar.xz, .txz)
--zstd    zstd compression        (.tar.zst)
-a        Pick compression from the file extension (create)
-C DIR    Change to DIR before doing anything
-p        Preserve permissions (default when extracting as root)
-P        Keep absolute paths (leading /) - use with care
-h        Follow symlinks and archive the files they point to

Memory aid

c = create   x = extract   t = list   z = gzip   f = file   v = verbose
tar -czvf  "compress, zip, verbose, file"
tar -xzvf  "extract, zip, verbose, file"

Create archives

tar -cf files.tar file1 file2 dir/             # plain tar, no compression
tar -czf backup.tar.gz ./project               # gzip
tar -cjf backup.tar.bz2 ./project              # bzip2
tar -cJf backup.tar.xz ./project               # xz (smaller, slower)
tar -caf backup.tar.zst ./project              # -a picks compression from the name
tar -czvf backup.tar.gz ./project              # verbose: show each file added
tar -czf "backup-$(date +%F).tar.gz" ./project # date-stamped name
tar -czf site.tar.gz -C /var/www html          # store as html/..., not /var/www/html/...

Extract archives

tar -xf archive.tar                            # modern tar detects compression
tar -xzf archive.tar.gz                        # gzip
tar -xjf archive.tar.bz2                       # bzip2
tar -xJf archive.tar.xz                        # xz
tar -xzvf archive.tar.gz                       # verbose
tar -xzf archive.tar.gz -C /opt/app            # extract into a directory (must exist)
tar -xzf archive.tar.gz path/in/archive.txt    # extract one file
tar -xzf archive.tar.gz --wildcards '*.conf'   # extract by pattern
tar -xzf archive.tar.gz --strip-components=1   # drop the top-level folder
tar -xzf archive.tar.gz --one-top-level        # extract into a folder named for the archive

List and inspect

tar -tf archive.tar.gz                         # list files
tar -tvf archive.tar.gz                        # long listing: perms, owner, size, date
tar -tf archive.tar.gz | head                  # peek at the first few entries
tar -tf archive.tar.gz | grep -c .             # count entries
tar -xOf archive.tar.gz path/file.txt          # print one file to the screen (-O = stdout)

Exclude and include

tar -czf out.tar.gz --exclude='*.log' ./project
tar -czf out.tar.gz --exclude='node_modules' --exclude='.git' ./project
tar -czf out.tar.gz --exclude-vcs ./project    # skip .git, .svn, etc.
tar -czf out.tar.gz -T filelist.txt            # read names to archive from a file
tar -czf out.tar.gz --exclude-from=skip.txt ./project

Add and update

tar -rf files.tar newfile.txt                  # append (uncompressed archives only)
tar -uf files.tar file1                        # update only if newer
tar --delete -f files.tar oldfile.txt          # remove a member (uncompressed only)

Pipelines and remote copies

tar -czf - ./project | ssh user@host 'cat > backup.tar.gz'
tar -czf - ./project | ssh user@host 'tar -xzf - -C /srv'   # copy a tree over SSH
ssh user@host 'tar -czf - /etc' > etc-backup.tar.gz         # pull a remote backup
tar -cf - ./src | (cd /dest && tar -xf -)                   # copy a tree, keeping perms
curl -sL https://example.com/app.tar.gz | tar -xz           # download and unpack
tar -czf - ./project | split -b 100M - part_                # split into 100MB chunks
cat part_* | tar -xzf -                                     # rejoin and extract
tar -cf - ./data | pv | gzip > data.tar.gz                  # progress bar (needs pv)

Incremental backups (GNU tar)

tar -czf full.tar.gz --listed-incremental=snap.file ./data     # level 0 (full)
tar -czf inc1.tar.gz --listed-incremental=snap.file ./data     # only changes since
tar -xzf full.tar.gz --listed-incremental=/dev/null            # restore in order

Practical one-liners

# Back up a home directory, skipping caches
tar -czf "home-$(date +%F).tar.gz" --exclude='.cache' --exclude='Downloads' ~

# See what is inside without extracting
tar -tzf archive.tar.gz | less

# Extract a tarball whose top folder you do not want
tar -xzf project-1.2.3.tar.gz --strip-components=1 -C ~/src/project

# Archive files modified in the last day
find . -mtime -1 -type f -print0 | tar -czf recent.tar.gz --null -T -

# Preserve owner, permissions and extended attributes (run as root)
tar --xattrs --acls -czpf system.tar.gz /etc

# Verify an archive is readable
tar -tzf archive.tar.gz > /dev/null && echo OK

# Compare an archive with what is on disk
tar -dzf archive.tar.gz -C /

# Handle a filename that starts with a dash
tar -czf out.tar.gz -- -weirdname.txt

Compression comparison

gzip (-z)    Fast, good compression, universal        .tar.gz  .tgz
bzip2 (-j)   Slower, smaller than gzip                .tar.bz2
xz (-J)      Slowest, smallest, great for releases    .tar.xz
zstd         Very fast, good ratio, modern            .tar.zst

Exit codes

    0 - success

    1 - some files changed while being archived (warning, archive is usually fine)

    2 - fatal error (missing file, bad archive, permission)

Tips

    tar strips the leading / from paths when creating, so extracting will not overwrite system files by surprise. -P turns that off.

    Old tar needs the compression flag when extracting (-z, -j, -J). Modern GNU tar auto-detects, so plain -xf works.

    Put -f last in a bundle of flags (-czf name, not -cfz name) because it takes the next word as the file name.

    Pointing -f at - means stdin or stdout, which is how tar fits into pipelines.

    Always list with -t before extracting an unknown archive. Look for absolute paths or ../ entries.

    Archive with a top-level folder (tar -czf x.tar.gz project/) so extracting does not spill files into the current directory.

    Wildcards in --exclude are matched by tar, so quote them. Wildcards in file lists are matched by the shell.

    bsdtar (macOS) differs slightly from GNU tar: --wildcards, --one-top-level and --listed-incremental are GNU-only.