tar & Compression Cheat Sheet
Create, extract and inspect tar archives, combine them with gzip/bzip2/xz compression, and work with zip - with the flags that actually matter day to day.
tar bundles a directory tree into a single archive file. On its own it doesn’t compress anything - that’s handled by piping through (or asking tar to invoke) a separate compressor like gzip, bzip2, or xz.
Core flags
tar -c # create a new archive
tar -x # extract an existing archive
tar -t # list the contents of an archive, without extracting
tar -v # verbose - print each file as it's processed
tar -f # read from / write to the FILE named next - almost always required
-f must be immediately followed by the archive filename - it’s easy to forget and have tar try to read from a tape device (its historical default) instead.
Creating an archive
tar -cvf backup.tar /home/user/documents/ # plain archive, no compression
tar -czvf backup.tar.gz /home/user/documents/ # -z: compress with gzip
tar -cjvf backup.tar.bz2 /home/user/documents/ # -j: compress with bzip2 (slower, smaller)
tar -cJvf backup.tar.xz /home/user/documents/ # -J: compress with xz (slowest, smallest)
The extension (.tar.gz, .tar.bz2, .tar.xz) is just a convention for humans - tar doesn’t read it to decide what to do. The compression flag (-z/-j/-J) is what actually matters.
Extracting an archive
tar -xvf backup.tar.gz # tar auto-detects gzip/bzip2/xz from the file itself
tar -xvf backup.tar.gz -C /tmp/restore/ # -C: extract into a specific directory instead of the current one
Modern
tarauto-detects the compression format when extracting, so you rarely need-z/-j/-Jon extract - only on create. Always extract into an empty or scratch directory first if you’re unsure what’s inside, rather than the current working directory.
Listing contents without extracting
tar -tvf backup.tar.gz # full listing with permissions/sizes/dates
tar -tvf backup.tar.gz | grep '\.conf' # check whether a specific file is in the archive
Always worth doing before extracting an archive from an untrusted source, or before overwriting anything.
Extracting only specific files
tar -xvf backup.tar.gz etc/nginx/nginx.conf # pull out just one file (path must match exactly as listed)
tar -xvf backup.tar.gz --wildcards 'etc/nginx/*' # pull out everything under one directory
Preserving permissions and ownership
sudo tar -xpvf backup.tar.gz -C /restore/ # -p: preserve original permissions (needs root to restore ownership fully)
Without -p, extracted files get default permissions based on your current umask, not the archive’s original modes - important for system files and backups being restored as root.
Excluding files when creating an archive
tar -czvf backup.tar.gz --exclude='*.log' --exclude='node_modules' /home/user/project/
tar -czvf backup.tar.gz -X exclude-list.txt /home/user/project/ # patterns from a file instead
# exclude-list.txt - one pattern per line
*.tmp
.cache
node_modules
Checking an archive’s compressed size before extracting
tar -tzvf backup.tar.gz | awk '{sum += $3} END {print sum, "bytes uncompressed"}' # total uncompressed size
ls -lh backup.tar.gz # compressed size on disk
Useful before extracting a large archive onto a disk with limited free space.
Compressing a single file (not a directory)
gzip file.txt # replaces file.txt with file.txt.gz, removes the original
gzip -k file.txt # -k: keep the original file too
gunzip file.txt.gz # decompress, replaces file.txt.gz with file.txt
bzip2 file.txt # same idea, better ratio, slower - produces file.txt.bz2
xz file.txt # best ratio, slowest - produces file.txt.xz
gzip/bzip2/xz compress a single file in place; they don’t bundle multiple files or directories the way tar does. That’s exactly why tar and a compressor are normally paired together.
Checking compression ratio
gzip -l file.txt.gz # shows compressed size, uncompressed size, and ratio
Working with .zip archives
zip -r archive.zip /home/user/documents/ # -r: recurse into directories
unzip archive.zip # extract into the current directory
unzip -l archive.zip # list contents without extracting
unzip archive.zip -d /tmp/restore/ # extract into a specific directory
.zip is the format to reach for when the archive needs to be opened on Windows or macOS without any extra tooling - tar.gz is the more common default on Linux-to-Linux transfers.
Splitting a large archive into parts
tar -czvf - /home/user/large-project/ | split -b 500M - backup.tar.gz.part- # split into 500MB chunks while creating
cat backup.tar.gz.part-* > backup.tar.gz # reassemble before extracting
Useful for archives too large for a single USB drive, email attachment, or upload limit.
Common recipes
# Full backup of a directory, timestamped, compressed
tar -czvf "backup-$(date +%F).tar.gz" /home/user/documents/
# Back up a remote server's directory straight to a local compressed archive over SSH
ssh user@remote-host "tar -czf - /var/www/example.com" > example-com-backup.tar.gz
# Restore that backup on a different machine
tar -xzvf example-com-backup.tar.gz -C /var/www/example.com/
# Archive everything except version control and dependencies before a deploy
tar -czvf release.tar.gz --exclude='.git' --exclude='node_modules' .
Safety notes
- Always
tar -tvfan unfamiliar archive before extracting it - a malicious or malformed archive can contain absolute paths (/etc/passwd) or../sequences aimed at writing outside the target directory. Moderntarstrips leading/and warns about../by default, but verifying contents first is still good practice. - Extract into a dedicated, empty directory when restoring anything important, rather than directly into a live directory - it’s much easier to compare and merge afterward than to undo an overwrite.
xzgives the smallest files but is the slowest to create and extract - fine for a one-time archive you’ll rarely touch again, a poor choice for backups you need to restore quickly under pressure.- Test a backup by actually extracting it (or at least listing it with
-tvf) periodically - an archive nobody has successfully restored from is not a verified backup.