Archiving and Compression¶
An archive bundles many files, with their paths, owners and permissions, into one stream; compression makes that stream smaller. tar does the first and hands the second to gzip, bzip2, xz or zstd, which is why most Linux downloads and backups end in .tar.gz, .tar.xz or .tar.zst.
Track: Core · Interview weight: Med
Must-Know Facts¶
| Fact | Value | Verify with |
|---|---|---|
| Create, list, extract | tar -c, -t, -x | tar -tf <archive> |
-f | The next argument is the archive file; without it, tar uses stdin or stdout | tar -tzf a.tgz |
-C <dir> | Change to <dir> before extracting or adding files | tar -xf a.tgz -C /opt |
| Compression flags | -z gzip, -j bzip2, -J xz, --zstd zstd | file <archive> |
| Extracting | GNU tar detects the compression; the flag is optional | tar -xf a.tar.xz |
| Absolute paths | Leading / is stripped on create | tar -tf |
| Permissions | Stored always; restored for root by default, -p for others | tar -tvf |
| Compressors | Ratio on typical text: xz > zstd > bzip2 > gzip; speed: zstd and gzip fastest, xz slowest | ls -l, time |
| Read compressed files | zcat, zless, zgrep; xzcat, bzcat, zstdcat | zcat f.gz |
| Useful extras | --exclude='*.log', --strip-components=1, one member by path | tar -tf <archive> |
zip | Archive and compression in one; common with Windows users | unzip -l f.zip |
tar Basics¶
tar -czvf site.tar.gz site
tar -tzvf site.tar.gz
mkdir restore
tar -xf site.tar.gz -C restore
ls -l restore/site/conf
Output:
site/
site/conf/
site/conf/nginx.conf
site/logs/
site/logs/access.log
drwxrwxr-x laborant/laborant 0 2026-09-16 14:01 site/
drwxrwxr-x laborant/laborant 0 2026-09-16 14:01 site/conf/
-rw-r----- laborant/laborant 10 2026-09-16 14:01 site/conf/nginx.conf
drwxrwxr-x laborant/laborant 0 2026-09-16 14:01 site/logs/
-rw-rw-r-- laborant/laborant 1288895 2026-09-16 14:01 site/logs/access.log
total 4
-rw-r----- 1 laborant laborant 10 Sep 16 14:01 nginx.conf
The archive kept mode 640 on nginx.conf. Read the flags as action (c, t, x), compression (z), v for a file list, and f followed by the archive name.
tar -xf site.tar.gz -C restore site/conf/nginx.conf
tar -czf nologs.tgz --exclude='*.log' site
tar -tzf nologs.tgz
tar -cJf site.tar.xz site
tar -xf site.tar.xz -C restore && echo "xz extracted without -J"
Output:
site/
site/conf/
site/conf/nginx.conf
site/logs/
xz extracted without -J
The -f Option and Old-Style Syntax¶
Without -f, GNU tar reads the archive from stdin, and refuses when stdin is a terminal:
tar -xzv site.tar.gz; echo "rc=$?"
Output:
tar: Refusing to read archive contents from terminal (missing -f option?)
tar: Error is not recoverable: exiting now
rc=2
Reading from a pipe is the one case where -f is not needed:
mkdir -p /tmp/gh
curl -fsSL https://github.com/cli/cli/releases/download/v2.63.2/gh_2.63.2_linux_amd64.tar.gz | tar -xzf - -C /tmp/gh
ls /tmp/gh/gh_2.63.2_linux_amd64
Output:
LICENSE
bin
share
-f - names stdin explicitly. Options without a dash are the old (BSD-style) form, where each letter that takes an argument consumes the next word in order:
tar Cxzf restore site.tar.gz && echo "old-style syntax worked"
Output:
old-style syntax worked
C took restore and f took site.tar.gz. The dashed form with -C at the end is clearer and is the one to use in scripts.
Absolute Paths¶
tar -czf /tmp/etc-ssh.tgz /etc/ssh/ssh_config
tar -tzf /tmp/etc-ssh.tgz
Output:
tar: Removing leading `/' from member names
etc/ssh/ssh_config
tar stores paths without the leading slash
Stored paths are relative, so extracting never overwrites /etc unless the command runs in / or uses -C /. The message goes to stderr and is harmless; -C / etc/ssh/ssh_config creates the archive without it.
Inspect archives from untrusted sources before extracting
tar -tvf shows paths and owners first. Extracting as root restores ownership and modes from the archive. GNU tar strips leading ../ from member names, but a crafted archive can still use symlinks to write outside the target directory.
Compressors Compared¶
The same 1.2 MB text log, compressed with each tool at its default level:
for c in gzip bzip2 xz zstd; do
start=$(date +%s.%N)
$c -q -k -f site/logs/access.log
end=$(date +%s.%N)
printf '%-6s %s\n' "$c" "$(awk -v s=$start -v e=$end 'BEGIN{printf "%.2fs", e-s}')"
done
ls -l site/logs/ | awk 'NR>1 {print $5, $9}'
Output:
gzip 0.03s
bzip2 0.04s
xz 0.21s
zstd 0.01s
1288895 access.log
255637 access.log.bz2
428483 access.log.gz
47552 access.log.xz
107311 access.log.zst
| Tool | Extension | tar flag | Use it for |
|---|---|---|---|
gzip | .gz, .tgz | -z | Compatibility; logs, web assets |
bzip2 | .bz2 | -j | Legacy archives |
xz | .xz | -J | Smallest files for distribution (kernel, packages) |
zstd | .zst | --zstd | Fast backups and container layers; tunable levels 1 to 19 |
-k keeps the original; without it, each compressor replaces the file. Compressors work on single files, which is why tar bundles first. gzip -l shows the ratio of a .gz file.
zip and cpio¶
zip -qr site.zip site
unzip -l site.zip | tail -3
find site -name '*.conf' | cpio -o -H newc 2>/dev/null > conf.cpio
cpio -it < conf.cpio
Output:
428483 2026-09-16 14:01 site/logs/access.log.gz
--------- -------
2127888 9 files
1 block
site/conf/nginx.conf
zip compresses each file separately and keeps a central index, so single files extract quickly. cpio reads file names from stdin; the newc format is how an initramfs is packed. 7z (p7zip) handles .7z and most other formats.
Common Errors¶
tar: Refusing to read archive contents from terminal (missing -f option?)¶
Cause: -f is missing, so tar tried to read the archive from the terminal.
Fix: tar -xzf site.tar.gz.
gzip: stdin: not in gzip format¶
Cause: the file is not gzip-compressed, often an HTML error page saved by curl without -f, or an archive compressed with another tool.
Fix: file archive.tar.gz; drop -z and let tar -xf detect the format.
tar: nosuch: Not found in archive¶
Cause: the member path does not match the stored path (a leading ./ or / difference is common).
Fix: tar -tf archive | grep <name> and use the exact stored path.
Interview Checkpoints¶
L1: What is the difference between archiving and compression?
Say first: archiving combines many files and their metadata into one stream (tar); compression shrinks a single stream (gzip, xz, zstd).
Proof: tar -cf a.tar dir produces a file about as large as the directory; gzip a.tar shrinks it.
Follow-up: Why does zip not need tar?
L1: Why does tar -xz archive.tgz fail in a terminal, but work with -f?
Say first: without -f, tar reads its archive from stdin, which is the terminal here, so it refuses; -f archive.tgz points it at the file instead.
Proof: tar -xz archive.tgz reports "Refusing to read archive contents from terminal"; tar -xzf archive.tgz extracts.
Follow-up: When is leaving out -f the right choice? (Piping an archive from curl or over ssh, where stdin is the source.)
L2: Back up /etc into a dated, compressed archive and verify it.
Say first: create with a date in the name, then list and test it.
Proof:
sudo tar -czf /backup/etc-$(date +%F).tar.gz -C / etc
tar -tzf /backup/etc-$(date +%F).tar.gz | head
gzip -t /backup/etc-$(date +%F).tar.gz && echo ok
Follow-up: How do you restore one file from it without extracting everything?
L2: Extract a release archive into /opt/app without its top-level directory.
Say first: extract into the target and strip one path component.
Proof: sudo tar -xzf app-1.4.tar.gz -C /opt/app --strip-components=1
Follow-up: How do you check the layout first? (tar -tzf app-1.4.tar.gz | head.)
L2: Copy a directory to another server without writing an archive to disk.
Say first: stream tar through ssh.
Proof: tar -czf - /srv/data | ssh host 'tar -xzf - -C /restore'
Follow-up: When would rsync -a be the better choice?
L3: A deployment script fails with gzip: stdin: not in gzip format.
Say first: check what was downloaded before debugging tar.
Proof: file release.tar.gz reports HTML document; the download returned an error page because curl ran without -f.
Follow-up: How do you make the script fail at the download step?
L3: Files extracted from a backup have the wrong owner and permissions.
Say first: check who extracted and with which options.
Proof: a non-root user gets its own ownership and the umask applied; root with tar -xpf (or --same-owner) restores both; tar -tvf shows what was stored.
Follow-up: Which extra options preserve ACLs and SELinux labels? (--acls --selinux --xattrs.)
Related¶
- File Operations:
cp -aandrsyncas alternatives - Finding Files: building file lists for
tarandcpio - File Types: identifying an archive with
file - Exit Codes and Chaining:
tarexits 2 on fatal errors
Captured on Rocky Linux 10.2 and Ubuntu 24.04.4 LTS (iximiuz Labs microVMs, kernel 6.1.167), 2026-09.