Skip to content
elephantoo

Archives & compression

Lesson 16 of 31 12 min read

tar, gzip, xz, zstd and zip: create, list, extract and choose the right format.


Backing up a website, shipping logs to a colleague, downloading a source release, deploying a build: all involve archives (many files bundled into one) and compression (making them smaller). On Linux these are usually two separate tools working together: tar bundles, and gzip, xz or zstd compress. You'll also meet zip for sharing with Windows users.

Practice project:

Terminal
mkdir -p ~/practice/ar && cd ~/practice/ar
mkdir -p project/src project/logs
seq 1 200000 > project/logs/app.log      # a 1.3 MB log
echo 'print("hi")' > project/src/main.py
echo "# Project" > project/README.md

tar: the tape archiver#

tar was designed for tape drives, hence the name, and its one-letter options read like a sentence:

LetterMeaning
cCreate an archive
xeXtract
tlisT contents
vVerbose: show each file
fFile: the archive name follows immediately
z / J / --zstdCompress with gzip / xz / zstd
-C dirChange to dir first (extract somewhere else)

Create

Terminal
tar -czf project.tar.gz project       # create, gzip, file name

Mnemonic: create zipped file. The archive name comes right after f, then what to put in it. tar -czf project project.tar.gz (swapped) tries to archive a file called project.tar.gz into an archive called project: an error, or worse, an overwrite.

List

Terminal
tar -tzf project.tar.gz
Output
project/
project/logs/
project/logs/app.log
project/src/
project/src/main.py
project/README.md

Add v (tar -tvzf) for permissions, owners, sizes and dates, like ls -l.

Extract

Terminal
tar -xzf project.tar.gz               # into the current directory
mkdir out && tar -xzf project.tar.gz -C out
ls out/project
Output
README.md  logs  src

Modern GNU tar detects the compression itself when extracting, so tar -xf anything.tar.xz works too. Extract a single file by naming it, or print it to stdout with -O:

Terminal
tar -xzf project.tar.gz project/README.md -O
Output
# Project

Exclude files

Terminal
tar -czf nologs.tar.gz --exclude='*.log' project
tar -tzf nologs.tar.gz
Output
project/
project/logs/
project/src/
project/src/main.py
project/README.md

Typical exclusions: --exclude=node_modules --exclude=.git --exclude='*.log'.

Choosing a compressor#

Same folder, different compressors (sizes in bytes):

Terminal
tar -cf project.tar project            # no compression
tar -czf project.tar.gz project        # gzip
tar -cJf project.tar.xz project        # xz
tar --zstd -cf project.tar.zst project # zstd
ls -l project.tar*
Output
1300480 project.tar
428951 project.tar.gz
58652 project.tar.xz
82088 project.tar.zst

(Columns trimmed to size and name. A file of sequential numbers compresses unusually well; real ratios depend on your data, and already-compressed files like JPEG, MP4 or ZIP barely shrink.)

ToolExtensionSpeedRatioUse when
gzip.gz, .tgzFastGoodDefault; works everywhere
xz.xzSlow to compressBestSoftware releases, long-term storage
zstd.zstVery fastVery goodBackups, logs, big data (modern default in many distros)
bzip2.bz2SlowGoodOlder archives (tar -cjf)

zstd may need sudo apt install zstd (Fedora: sudo dnf install zstd).

Compressing single files#

gzip, xz and zstd also work on their own, one file at a time:

Terminal
cp project/logs/app.log big.log
gzip big.log            # big.log → big.log.gz (the original is REPLACED)
gzip -l big.log.gz      # compression stats
zcat big.log.gz | tail -1   # read without decompressing to disk
gunzip big.log.gz       # back to big.log
gzip -k big.log         # keep the original as well
Output
         compressed        uncompressed  ratio uncompressed_name
             428480             1288895  66.8% big.log
200000

The z family reads compressed files directly: zcat, zless, zgrep "ERROR" app.log.gz. That's how you search rotated logs like /var/log/syslog.2.gz. For xz, xz/unxz/xzcat; for zstd, zstd/unzstd/zstdcat (zstd keeps the original by default).

zip and unzip#

For archives that Windows and macOS users can open with a double-click:

Terminal
sudo apt install zip unzip         # Fedora: sudo dnf install zip unzip
zip -r project.zip project -x '*.log'
unzip -l project.zip               # list
unzip project.zip -d extracted     # extract into a folder
Output
Archive:  project.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
        0  2026-10-01 10:50   project/
        0  2026-10-01 10:50   project/logs/
        0  2026-10-01 10:50   project/src/
       12  2026-10-01 10:50   project/src/main.py
       10  2026-10-01 10:50   project/README.md
---------                     -------
       22                     5 files

zip compresses each file separately and doesn't preserve Linux permissions and owners as faithfully as tar, so use tar for Linux-to-Linux backups and deployments. zip -e adds a password, but its default encryption is weak; use gpg or 7z for real secrecy.

Real-world recipes#

Terminal
# Dated backup of a website
tar -czf "site-$(date +%F).tar.gz" -C /var/www mysite

# Stream an archive over SSH without a temporary file
tar -czf - project | ssh user@server 'tar -xzf - -C /srv'

# Download and unpack a release in one step
curl -L https://example.com/tool-1.2.tar.gz | tar -xz

# Back up /etc preserving permissions (needs root to read everything)
sudo tar -czpf etc-backup.tar.gz /etc

- as the file name means stdin/stdout, which is what makes the streaming tricks work. -C /var/www mysite stores paths as mysite/... rather than var/www/mysite/.... GNU tar strips the leading / from absolute paths (with a warning), so restoring an archive never overwrites system files unless you extract with -C /.

Safety when extracting#

  • List first (tar -tf, unzip -l). Well-behaved archives contain one top-level folder; badly made ones dump hundreds of files into your current directory (a "tarbomb").
  • Extract unknown archives into an empty directory: mkdir tmp && tar -xf thing.tar.gz -C tmp.
  • Don't extract archives from untrusted sources as root: tar preserves ownership and permissions for root, and paths containing ../ could write outside the target.

Common mistakes#

  • Putting the archive name somewhere other than straight after f.
  • Forgetting that gzip file deletes the original.
  • Compressing already-compressed media and expecting savings.
  • Using zip for server backups and losing permissions.
  • Archiving a live database's files directly. Dump it first (mysqldump, pg_dump) and archive the dump.

What's next#

Archives are one way to package things up. Next you'll customise the shell itself, with environment variables, PATH, aliases and .bashrc.

Check your understanding

Quick quiz

0/3 answered
  1. 1.Which command creates a gzip-compressed archive site.tar.gz of the folder site/?

  2. 2.You run gzip notes.txt. What happens to the original file?

  3. 3.Before extracting an archive you downloaded, what is a good habit?

Finished reading?

Mark this lesson complete to track your progress.