Linux: Archives and Compression

Data backup is the lifeline of operations. On Linux, tar + gzip is the most universal archiving solution, and rsync is the most powerful incremental sync tool.

📋 Prerequisites: You should already know

1. What You'll Learn


2. A Story of "Forgetting the Exclude Parameter"

(1) The Pain Point: Packed Things That Shouldn't Be Packed

Xiaoming needed to send a project folder to a colleague — the team agreed not to transfer node_modules and .git directories because they're too large and unnecessary.

(2) One Command for a Perfect Archive

BASH
tar -czf project.tar.gz \
    --exclude=node_modules \
    --exclude=.git \
    --exclude=__pycache__ \
    project/

(3) The Benefit: A Clean Package

Xiaoming's compressed archive went from 500MB (with node_modules) down to 2MB. His colleague could use it right after extracting.


3. Knowledge Points

(1) tar — Archiving Tool

BASH
# Create tar archive
tar -cf archive.tar file1 file2 dir/    # Archive
tar -czf archive.tar.gz dir/            # Archive + gzip compression

> 💡 Tip: `tar -czf` option mnemonic — `c` (create), `z` (gzip compress), `f` (file, specify filename). This is the most common combination; the resulting `.tar.gz` file is the standard distribution format in the Linux world. To extract, just replace `c` with `x` (extract): `tar -xzf`.
tar -cjf archive.tar.bz2 dir/           # Archive + bzip2 compression
tar -cJf archive.tar.xz dir/            # Archive + xz compression

# Extract
tar -xf archive.tar                     # Extract (auto-detects format)
tar -xzf archive.tar.gz                 # Extract .tar.gz
tar -xf archive.tar -C /target/dir/     # Extract to specified directory

# View contents
tar -tf archive.tar.gz                  # Preview file list inside archive

> ⚠️ Warning: Before extracting a tar archive, use `tar -tf` to preview the file list — confirm there are no "bomb files" (e.g., files that extract to massive numbers of small files, or paths starting with `/` indicating absolute paths), to avoid overwriting system files or filling up disk space.

# Exclude
tar -czf backup.tar.gz --exclude="*.log" --exclude=node_modules dir/
tar Option Meaning
-c Create archive
-x Extract
-t List contents
-f Specify archive filename
-z Filter through gzip
-j Filter through bzip2
-J Filter through xz
-v Show processed files
-C Extract to specified directory
--exclude Exclude files matching pattern

(2) Compression Algorithm Comparison

Algorithm Extension Option Compression Ratio Speed Use Case
gzip .gz -z Medium Fast Daily backup and distribution
bzip2 .bz2 -j High Slow When higher compression is needed
xz .xz -J Highest Slowest Long-term archiving, minimum size

(3) zip/unzip — Cross-Platform Compression

TEXT
# Compress
zip -r project.zip project/             # Recursively compress directory
zip -r project.zip project/ -x "*.git*" # Exclude .git
zip -r project.zip project/ -P password # Encrypt

# Extract
unzip project.zip                       # Extract to current directory
unzip project.zip -d /target/dir/       # Extract to specified directory
unzip -l project.zip                    # View contents without extracting

# zip advantage: natively supported on all operating systems

(4) rsync — Incremental Sync

BASH
# Basic usage
rsync -av source/ destination/          # Local sync (recursive + preserve attributes)
rsync -av --delete source/ dest/        # Sync and delete files in dest that aren't in source

> ℹ️ Note: `rsync --delete` makes the destination match the source exactly — files in the destination that don't exist in the source will be deleted. If you make a mistake (e.g., wrong source path), it could delete a large amount of destination data. Always add `--dry-run` first to preview operations before executing.
rsync -avz source/ user@host:/dest/     # Remote sync (compressed transfer)
rsync -avz -e "ssh -p 2222" source/ host:/dest/  # Specify SSH port

# Exclude
rsync -av --exclude="node_modules" --exclude=".git" src/ dst/

# Incremental backup (hard links)
rsync -av --link-dest=../backup-yesterday/ src/ backup-today/

rsync Advantages:

(5) ▶ Example: tar Archive and Extract

TEXT
# Archive the projects directory under home
tar -czf projects-backup.tar.gz ~/projects/

# View archive contents
tar -tf projects-backup.tar.gz | head -10

# Extract to /tmp
tar -xzf projects-backup.tar.gz -C /tmp/

# With verbose output
tar -czvf my-backup.tar.gz --exclude="*.log" /var/log/

(6) ▶ Example: Compression Algorithm Comparison

BASH
# Prepare test data
mkdir -p /tmp/compress-test
cp -r /usr/share/doc/* /tmp/compress-test/ 2>/dev/null

# gzip
time tar -czf test.tar.gz -C /tmp compress-test
ls -lh test.tar.gz

# bzip2
time tar -cjf test.tar.bz2 -C /tmp compress-test
ls -lh test.tar.bz2

# xz
time tar -cJf test.tar.xz -C /tmp compress-test
ls -lh test.tar.xz

# Comparison results
# Typically: test.tar.gz is largest but fastest, test.tar.xz is smallest but slowest

Output:

TEXT
-rw-r--r-- 1 alice alice 1.2M test.tar.gz

real    0m0.234s
user    0m0.198s
sys     0m0.036s
-rw-r--r-- 1 alice alice 856K test.tar.bz2

real    0m1.456s
user    0m1.389s
sys     0m0.067s
-rw-r--r-- 1 alice alice 612K test.tar.xz

real    0m5.123s
user    0m4.987s
sys     0m0.136s

(7) ▶ Example: zip Cross-Platform Distribution

TEXT
# Archive a project (excluding unneeded directories)
cd ~/projects
zip -r myapp.zip myapp/ -x "myapp/node_modules/*" "myapp/.git/*" "myapp/__pycache__/*"

# View contents
unzip -l myapp.zip | head -20

# Encrypt archive
zip -r -e secret.zip confidential/    # Will prompt for password

(8) ▶ Example: rsync Backup

BASH
# Local backup
rsync -av --delete ~/projects/ /backup/projects/

# Remote backup to server
rsync -avz -e "ssh -i ~/.ssh/mykey" \
    --exclude="node_modules" \
    --progress \
    ~/projects/ user@backup-server:/backups/

# Incremental backup (using hard links)
# Day 1
rsync -av /data/ /backup/2026-07-07/

# Day 2 (only stores changes)
rsync -av --link-dest=/backup/2026-07-07/ /data/ /backup/2026-07-08/

Output:

TEXT
sending incremental file list
sent 1,234 bytes  received 512 bytes  2,492.00 bytes/sec
total size is 5.6M  speedup is 3,210.45

sending incremental file list
app.js
config.yaml
sent 4,567 bytes  received 128 bytes  9,390.00 bytes/sec
total size is 5.6M  speedup is 1,197.23

(9) ▶ Example: Automated Backup Script

BASH
#!/bin/bash
# auto-backup.sh - Automated backup of critical directories

BACKUP_ROOT="/backup"
DATE=$(date +%Y%m%d)
RETENTION_DAYS=30

# Directories to back up
declare -A DIRS
DIRS["projects"]="$HOME/projects"
DIRS["configs"]="/etc"
DIRS["notes"]="$HOME/notes"

echo "=== Starting backup: $DATE ==="

# Create backup directory
mkdir -p "$BACKUP_ROOT/$DATE"

for name in "${!DIRS[@]}"; do
    src="${DIRS[$name]}"
    dest="$BACKUP_ROOT/$DATE/$name.tar.gz"
    
    if [ -d "$src" ]; then
        echo "Backing up $src → $dest"
        tar -czf "$dest" \
            --exclude="node_modules" \
            --exclude=".git" \
            --exclude="*.log" \
            "$src" 2>/dev/null
        echo "  ✅ $(du -h "$dest" | cut -f1)"
    else
        echo "  ⚠️ Directory does not exist: $src"
    fi
done

# Delete expired backups
echo ""
echo "Cleaning backups older than $RETENTION_DAYS days..."
find "$BACKUP_ROOT" -maxdepth 1 -type d -mtime +$RETENTION_DAYS -exec rm -rf {} \;

echo "=== Backup complete ==="

Output:

TEXT
=== Starting backup: 20260707 ===
Backing up /home/alice/projects → /backup/20260707/projects.tar.gz
  ✅ 12M
Backing up /etc → /backup/20260707/configs.tar.gz
  ✅ 4.5M
Backing up /home/alice/notes → /backup/20260707/notes.tar.gz
  ✅ 256K

Cleaning backups older than 30 days...
=== Backup complete ===

(10) ▶ Comprehensive Example: Complete rsync Backup Solution

BASH
#!/bin/bash
# rsync-backup.sh - Incremental backup using rsync

SOURCE="$HOME/projects/webapp"
DEST_USER="backup"
DEST_HOST="backup.example.com"
DEST_PATH="/backups/webapp"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
LOGFILE="/var/log/backup.log"

log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOGFILE"
}

log "Starting backup of $SOURCE..."

# Perform remote incremental backup using rsync
rsync -avz \
    --delete \
    --partial \
    --progress \
    --exclude="node_modules" \
    --exclude=".git" \
    --exclude=".env" \
    --exclude="tmp/" \
    -e "ssh -i ~/.ssh/backup_key -p 22" \
    "$SOURCE/" \
    "${DEST_USER}@${DEST_HOST}:${DEST_PATH}/current/" >> "$LOGFILE" 2>&1

if [ $? -eq 0 ]; then
    log "✅ Backup succeeded"
    # Create timestamped snapshot
    ssh -i ~/.ssh/backup_key "${DEST_USER}@${DEST_HOST}" \
        "cp -al ${DEST_PATH}/current ${DEST_PATH}/${TIMESTAMP}"
    log "✅ Snapshot created: $TIMESTAMP"
else
    log "❌ Backup failed (exit code: $?)"
    exit 1
fi

❓ FAQ

Q: What's the relationship between tar and gzip? A: tar only handles archiving (combining multiple files into one), not compression. gzip handles compression. The common combination tar -czf is equivalent to tar archive → gzip compress. File extensions: .tar.gz or .tgz.

Q: What do -c, -z, -f mean in tar -czf? A: -c (create) creates the archive, -z (gzip) compresses with gzip, -f (file) specifies the archive filename. The shorthand tar -czf can also be written as tar -c -z -f.

Q: Which is better for cross-platform use, zip or tar.gz? A: zip has better cross-platform compatibility — Windows/macOS/Linux all natively support it. tar.gz is the standard in the Linux/Unix world; Windows needs third-party tools like 7-Zip.

Q: What makes rsync faster than scp? A: rsync uses an incremental transfer algorithm — it only sends the changed parts of files. scp always copies entire files. For repeated transfers of the same files with small changes, rsync is much faster.

Q: How to do incremental instead of full backups? A: rsync inherently only transfers increments (changed parts). Combined with --link-dest to create hard-link snapshots: the first run is full, then each day use --link-dest referencing the previous day's snapshot, storing only the changes.


📖 Summary


📝 Exercises

  1. Basic (⭐): Archive ~/projects or a test directory as backup.tar.gz, use -v to observe the process, then use tar -tf to view the file list inside
  2. Intermediate (⭐⭐): Extract to /tmp/test and verify file integrity, then create a test directory, zip it (excluding a subdirectory), and unzip to another location
  3. Challenge (⭐⭐⭐): Use rsync to sync a local directory to /tmp/backup/, verify incremental transfer (modify a file and sync again, observing only the change was transferred), then write a backup script supporting both tar.gz full backup and rsync incremental backup modes
Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏