There’s one command that trips up half the internet: tar. Not because it’s hard, it’s simple, but because the flag mnemonic is so overused that everyone’s confused about what it actually means.
You don’t need to memorize every variation. Once you understand the create / extract / list pattern and the compression flags, you’re golden. Let me break it down before you go cargo-culting xvzf into your deploy scripts.
The Core Flags: Extract vs Create vs List
Tar has three main modes. Pick one:
- x = extract (unpack)
- c = create (pack into tarball)
- t = list (show contents without extracting)
Then add compression flags and modifiers:
- z = gzip compression (.tar.gz, .tgz)
- j = bzip2 compression (.tar.bz2)
- J = xz compression (.tar.xz)
- v = verbose (show file names as they extract)
- f = file (the next argument is the filename)
That’s it. Everything else is built from these.
The Classic Example (And Why It Works)
tar xvzf archive.tar.gzReading left to right:
- x = extract
- v = verbose output
- z = gzip decompression
- f = next arg is the filename
The mnemonic that haunts everyone: “extract verbosely from gzip file”. The internet calls it xvzf, so people just copy-paste it. The order of the mode and compression letters doesn’t really matter, but the golden rule is that f comes last in the bundle so the filename can follow right after it: tar xvzf archive.tar.gz. Put f in the middle and tar grabs the wrong argument as the filename.
Modern tar is smart: tar xf archive.tar.gz auto-detects the compression. You often don’t need the z flag anymore.
Compression Formats: tar.gz vs tar.bz2 vs tar.xz
Each format trades off speed vs compression ratio:
| Format | Size | Speed | Command |
|---|---|---|---|
| .tar.gz | Medium | Fast | tar xvzf file.tar.gz |
| .tar.bz2 | Small | Slow | tar xvjf file.tar.bz2 |
| .tar.xz | Smallest | Slowest | tar xvJf file.tar.xz |
Gzip (z): Default. Balances speed and compression. Most common on the internet.
Bzip2 (j): Smaller files, slower to compress/extract. Used in old RedHat/CentOS repos.
XZ (J): Best compression, slowest. Modern standard for kernel downloads and Linux distributions.
# Extract any of these (modern tar detects compression)tar xf archive.tar.gztar xf archive.tar.bz2tar xf archive.tar.xz
# Or be explicittar xzf archive.tar.gz # gziptar xjf archive.tar.bz2 # bzip2tar xJf archive.tar.xz # xz (capital J)Extract to a Specific Directory
Don’t clutter your current directory. Use -C to extract into a target:
tar xvzf archive.tar.gz -C /target/directoryThis extracts everything inside /target/directory. The directory must exist, or you’ll get an error. If you need to create it first:
mkdir -p /target/directory && tar xvzf archive.tar.gz -C /target/directoryWhy -C matters: Many tarballs come with a top-level directory (archive/file1, archive/file2). Without -C, they dump into your current dir. With -C, they nest properly. Always check first.
List Contents Without Extracting
See what’s in a tarball before you extract:
# List all filestar tvzf archive.tar.gz
# Just file names (no details)tar tzf archive.tar.gz
# Count filestar tzf archive.tar.gz | wc -l
# Find a specific filetar tzf archive.tar.gz | grep "config"The t flag (list) is your friend when you’re skeptical about what you’re extracting.
Create a Tarball
Package your own files:
# Create tar.gz from a directorytar czf archive.tar.gz /path/to/directory/
# Create tar.bz2tar cjf archive.tar.bz2 /path/to/directory/
# Create tar.xztar cJf archive.tar.xz /path/to/directory/Exclude Files During Creation (or Extraction)
Don’t pack everything:
# Exclude node_modules and .git when creatingtar czf project.tar.gz /path/to/project \ --exclude=node_modules \ --exclude=.git \ --exclude=.DS_StoreFor extraction (rare), exclude during unpacking:
tar xzf archive.tar.gz --exclude="*/tests/*"Extract a Single File
Pull one file from the tarball without extracting the whole thing:
tar xvzf archive.tar.gz path/to/file.txtThis extracts only path/to/file.txt and recreates the directory structure. Useful for grabbing a config file from a backup.
Gotchas That Bite You
1. Leading ./ Gets Stripped
When you create a tarball with tar czf archive.tar.gz ./mydir, tar stores it as mydir/file, not ./mydir/file. When someone extracts, the leading ./ doesn’t exist. Not a problem 99% of the time, but if you’re distributing software, be aware.
2. Absolute Paths Become Relative
If you pack /etc/config.txt, tar strips the leading / and stores it as etc/config.txt. This is a safety feature: extracting a tar that has absolute paths would overwrite your system files. Always use relative paths when creating:
# Goodtar czf backup.tar.gz -C /etc config.txt
# Risky (but tar will warn you)tar czf backup.tar.gz /etc/config.txt3. Permission Hell
Tarballs preserve file permissions. If you extract a tarball as root, the files stay owned by whatever UID was in the tarball (often a random number from another system), use --no-same-owner if you’re deploying:
tar xzf archive.tar.gz --no-same-ownerOne-Liners That Save Time
# List the first 20 entries (verbose listing, no extraction)tar tvzf archive.tar.gz | head -20
# Find the biggest files in a tarball (verbose list shows sizes)tar tvzf archive.tar.gz | sort -k3 -n | tail -5
# Dump one file straight to stdout (no extraction to disk)tar xzOf archive.tar.gz path/to/file.txt
# Total uncompressed size before extracting (sum the size column)tar tvzf archive.tar.gz | awk '{sum += $3} END {print sum " bytes"}'The Cheat Sheet
| Task | Command |
|---|---|
| Extract tar.gz | tar xf file.tar.gz |
| Extract tar.bz2 | tar xf file.tar.bz2 |
| Extract tar.xz | tar xf file.tar.xz |
| List contents | tar tf file.tar.gz |
| Create tar.gz | tar czf archive.tar.gz /path/ |
| Extract to dir | tar xf file.tar.gz -C /target |
| Extract one file | tar xf file.tar.gz path/to/file |
| Exclude on create | tar czf archive.tar.gz --exclude=dir /path/ |
Forget the mnemonics. Just remember: x to extract, c to create, t to list. Add your compression letter and f, and you’re done. Stop overthinking it.