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

Auto-detect on Extract

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

Extract to Specific Directory

1
tar -xzvf archive.tar.gz -C /destination/path

Extract Single File

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'

Extract from Remote

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

Extract Strip Components

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

TaskCommand
Createtar -cvf archive.tar files/
Create gziptar -czvf archive.tar.gz files/
Extracttar -xvf archive.tar
Extract to dirtar -xvf archive.tar -C /dest
Listtar -tvf archive.tar
Exclude--exclude='pattern'
Preserve perms-p
Strip path--strip-components=N

Compression Flags

FormatCreateExtract
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.