tar (tape archive) bundles files and directories into a single file. Combined with compression, it’s the standard way to package and distribute files on Unix systems.
The Basics#
1
2
3
4
5
6
7
8
| # Create archive
tar -cvf archive.tar /path/to/files
# Extract archive
tar -xvf archive.tar
# List contents
tar -tvf archive.tar
|
Understanding the Flags#
1
2
3
4
5
| c = Create archive
x = Extract archive
t = List contents
v = Verbose (show files)
f = File (next arg is filename)
|
So tar -cvf = Create, Verbose, File.
Compression#
gzip (.tar.gz or .tgz)#
1
2
3
4
5
| # Create compressed
tar -czvf archive.tar.gz /path/to/files
# Extract
tar -xzvf archive.tar.gz
|
bzip2 (.tar.bz2)#
1
2
3
4
5
| # Create (better compression, slower)
tar -cjvf archive.tar.bz2 /path/to/files
# Extract
tar -xjvf archive.tar.bz2
|
xz (.tar.xz)#
1
2
3
4
5
| # Create (best compression, slowest)
tar -cJvf archive.tar.xz /path/to/files
# Extract
tar -xJvf archive.tar.xz
|
1
2
3
4
| # Modern tar auto-detects compression
tar -xvf archive.tar.gz
tar -xvf archive.tar.bz2
tar -xvf archive.tar.xz
|
Common Operations#
Create Archive of Directory#
1
| tar -czvf backup.tar.gz /home/user/documents
|
1
| tar -xzvf archive.tar.gz -C /destination/path
|
1
| tar -xzvf archive.tar.gz path/to/specific/file.txt
|
Add Files to Existing Archive#
1
2
| # Only works with uncompressed tar
tar -rvf archive.tar newfile.txt
|
Update Changed Files#
1
2
| # Only works with uncompressed tar
tar -uvf archive.tar /path/to/files
|
Excluding Files#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # Exclude pattern
tar -czvf archive.tar.gz --exclude='*.log' /path
# Exclude directory
tar -czvf archive.tar.gz --exclude='node_modules' /path
# Multiple exclusions
tar -czvf archive.tar.gz \
--exclude='*.log' \
--exclude='tmp/' \
--exclude='.git' \
/path
# Exclude from file
tar -czvf archive.tar.gz --exclude-from=exclude.txt /path
|
Preserving Permissions#
1
2
3
4
5
6
7
8
| # Preserve permissions (default for root)
tar -cpvf archive.tar /path
# Preserve with compression
tar -cpzvf archive.tar.gz /path
# Extract preserving permissions
tar -xpvf archive.tar
|
Incremental Backups#
1
2
3
4
5
| # Full backup (creates snapshot file)
tar -czvf full.tar.gz -g snapshot.snar /path
# Incremental (only changed files)
tar -czvf incremental.tar.gz -g snapshot.snar /path
|
Working with Remote Archives#
Create on Remote via SSH#
1
| tar -czvf - /local/path | ssh user@remote 'cat > /remote/archive.tar.gz'
|
1
| ssh user@remote 'cat /remote/archive.tar.gz' | tar -xzvf - -C /local/path
|
Direct Remote Sync#
1
2
| # Archive and extract in one command (like rsync)
tar -C /source -cf - . | ssh user@remote 'tar -C /dest -xf -'
|
Practical Examples#
Backup Home Directory#
1
2
3
4
| tar -czvf ~/backup-$(date +%Y%m%d).tar.gz \
--exclude='.cache' \
--exclude='Downloads' \
~
|
Archive Project (excluding junk)#
1
2
3
4
5
6
| tar -czvf project.tar.gz \
--exclude='node_modules' \
--exclude='.git' \
--exclude='*.log' \
--exclude='dist' \
./project
|
Create Distributable Package#
1
2
3
4
| VERSION="1.0.0"
tar -czvf myapp-$VERSION.tar.gz \
--transform "s,^,myapp-$VERSION/," \
src/ docs/ README.md LICENSE
|
Verify Archive Integrity#
1
2
3
4
5
| # Test without extracting
tar -tzvf archive.tar.gz > /dev/null && echo "OK"
# With gzip integrity check
gzip -t archive.tar.gz && echo "OK"
|
Split Large Archive#
1
2
3
4
5
| # Create split archive
tar -czvf - /large/directory | split -b 100M - archive.tar.gz.
# Combine and extract
cat archive.tar.gz.* | tar -xzvf -
|
Encrypt Archive#
1
2
3
4
5
6
7
8
| # Create encrypted archive
tar -czvf - /path | gpg -c > archive.tar.gz.gpg
# Extract encrypted archive
gpg -d archive.tar.gz.gpg | tar -xzvf -
# With openssl
tar -czvf - /path | openssl enc -aes-256-cbc -e > archive.tar.gz.enc
|
Comparing Archives#
1
2
3
4
5
| # Diff archive with filesystem
tar -dvf archive.tar /path
# Compare two archives
diff <(tar -tf archive1.tar | sort) <(tar -tf archive2.tar | sort)
|
Progress Display#
1
2
3
4
5
6
| # With pv (pipe viewer)
tar -cf - /large/directory | pv | gzip > archive.tar.gz
# Estimate size first
SIZE=$(du -sb /path | cut -f1)
tar -cf - /path | pv -s $SIZE | gzip > archive.tar.gz
|
Common Gotchas#
Absolute vs Relative Paths#
1
2
3
4
5
6
7
8
| # Creates absolute paths in archive (often unwanted)
tar -cvf archive.tar /home/user/files
# Use -C to change directory first
tar -cvf archive.tar -C /home/user files
# Or strip leading slash
tar -cvf archive.tar --strip-components=1 /home/user/files
|
1
2
3
4
| # Archive contains: project-1.0/src/main.c
# Extract without top directory
tar -xvf archive.tar --strip-components=1
# Results in: src/main.c
|
Overwrite Behavior#
1
2
3
4
5
| # Don't overwrite newer files
tar -xvf archive.tar --keep-newer-files
# Keep all existing files
tar -xvf archive.tar --skip-old-files
|
Quick Reference#
| Task | Command |
|---|
| Create | tar -cvf archive.tar files/ |
| Create gzip | tar -czvf archive.tar.gz files/ |
| Extract | tar -xvf archive.tar |
| Extract to dir | tar -xvf archive.tar -C /dest |
| List | tar -tvf archive.tar |
| Exclude | --exclude='pattern' |
| Preserve perms | -p |
| Strip path | --strip-components=N |
Compression Flags#
| Format | Create | Extract |
|---|
| gzip | -z | -z (or auto) |
| bzip2 | -j | -j (or auto) |
| xz | -J | -J (or auto) |
tar’s flags seem cryptic until you realize they’re just abbreviations: create, extract, test, verbose, file, gzip. Modern tar auto-detects compression on extract, so you often just need tar -xvf regardless of the compression format. Master the basics, learn the exclusion patterns, and you’ll handle any archive task.
📬 Get the Newsletter
Weekly insights on DevOps, automation, and CLI mastery. No spam, unsubscribe anytime.