tar Cheatsheet - tar Archive & Compression Reference
Bundling a directory before a backup, a code hand-off or a server migration always goes through tar, and the difficulty is choosing a compression format and avoiding parameters that cause irreversible damage. The sheet separates creating, listing, testing and extracting, then gives formats their own comparison: gzip as a balanced default, bzip2 smaller but slower, xz best ratio with threading at a time cost, and zstd as the pragmatic modern choice. Two behaviours matter for backups: tar records ownership by default, so extraction without --no-same-owner silently changes file owners, and --exclude decides what never enters the archive — node_modules, .git and caches belong there. The riskiest moment is extraction, where an archive containing ../ entries can write outside the target directory, so list with tar -tf before unpacking. Two performance notes: parallel compression with pigz for large trees, and --strip-components to avoid an extra nesting level on extraction.
Typical Use Case
For developers backing up directories, migrating servers and packaging releases. tar is not hard to remember commands for; it is hard on three counts: choosing a compression format (the speed versus ratio trade-off across gzip, zstd and xz), the trailing slash that decides whether you archive a directory or its contents, and the irreversibility of overwriting during extraction. This sheet covers packing, extraction, inspection, format comparison and advanced usage, with --exclude and --strip-components as the two parameters that save the most time and cause the most damage.
Pack & Compress 7
tar -cvf archive.tar dir/tar -czvf archive.tar.gz dir/tar -cjvf archive.tar.bz2 dir/tar -cJvf archive.tar.xz dir/tar --zstd -cvf archive.tar.zst dir/tar -czvf archive.tar.gz --exclude="*.log" dir/tar -czvf archive.tar.gz --exclude="node_modules" --exclude=".git" project/Extract 8
tar -xvf archive.tartar -xzvf archive.tar.gztar -xjvf archive.tar.bz2tar -xJvf archive.tar.xztar --zstd -xvf archive.tar.zsttar -xzvf archive.tar.gz -C /opt/tar -xzvf archive.tar.gz file.txttar -xzvf archive.tar.gz --strip-components=1List & Test 5
tar -tf archive.tar.gztar -tzvf archive.tar.gztar -tf archive.tar.gz | grep "config"gzip -t archive.tar.gztar -dvf archive.tarCompression Format Comparison 6
-z (gzip)-j (bzip2)-J (xz)--zstd (zstd)-a--use-compress-program=pigzOther Compression Tools 8
zip -r archive.zip dir/unzip archive.zip -d /opt/unzip -l archive.zipgzip file.txtgzip -k file.txtgunzip file.txt.gzzcat file.txt.gz7z x archive.7zAdvanced Usage 6
tar -rvf archive.tar newfile.txttar -uvf archive.tar dir/tar -czf - dir/ | ssh host "tar -xzf - -C /dest"tar -czf - dir/ | split -b 100M - archive.tar.gz.cat archive.tar.gz.* | tar -xzvf -tar -g snapshot.snar -czf backup.tar.gz dir/Common Examples 4
tar -czvf backup-$(date +%F).tar.gz /home/user/tar -czvf app.tar.gz --exclude="*.log" --exclude="tmp/" app/tar -xzvf package.tar.gz --strip-components=1 -C /opt/apptar -czf - /data | pigz > backup.tar.gzParameter matrix
| Parameter | Effect | Example |
|---|---|---|
-z (gzip) | Fastest and most compatible. | tar -czvf a.tar.gz dir/ |
--zstd | Speed close to gzip with better compression; recommended on newer systems. | tar --zstd -cvf a.tar.zst dir/ |
-J (xz) | Highest compression but the slowest. | tar -cJvf a.tar.xz dir/ |
-c / -x / -t | Create / extract / list without extracting. | tar -tf a.tar.gz |
-v | Shows the filenames being processed. | tar -czvf a.tar.gz dir/ |
--exclude | Excludes paths or patterns at pack time. | --exclude="*.log" --exclude="node_modules/" |
--strip-components=N | Strips the first N directory levels at extract time. | tar -xzf a.tar.gz --strip-components=1 -C /opt |
-C dir | Changes to the specified directory for the operation. | tar -xzf a.tar.gz -C /opt/app |
-k | Keeps the original file when gzip compressing. | gzip -k file.txt |
pigz | Multi-threaded compression for large directories. | tar -czf - /data | pigz > b.tar.gz |
split -b 100M | Splits into volumes for easier transfer. | tar -czf - dir/ | split -b 100M - a.tar.gz. |
gzip -t | Tests archive integrity; no output means it is fine. | gzip -t a.tar.gz |
Common pitfalls
SymptomAfter extraction there is an extra directory level, producing structures like /opt/app/app/.
CauseThe source directory was written incorrectly at pack time, or the top level was not stripped at extract time.
FixExtract with --strip-components=1, or pack with -C dir . so the contents carry no top-level directory.
SymptomThe archive is enormous, with node_modules and .git inside.
CauseNo --exclude was used.
Fixtar -czvf a.tar.gz --exclude="node_modules/" --exclude=".git" --exclude="*.log" app/
SymptomExtraction to a specified directory fails with a permission or non-existent path error.
CauseThe target directory was not created.
FixRun mkdir -p /opt/app first, then point -C at it.
SymptomUsing tar -r to append a file to a .tar.gz errors out.
CauseAppending is only supported for uncompressed .tar archives.
FixRepack when you need to add content, or decompress with gzip -d, append, and recompress.
SymptomExtraction prints path-traversal warnings or files land in unexpected places.
CauseThe archive contains ../ entries or absolute paths.
FixInspect the entry list with tar -tf first, and extract unknown packages into an isolated directory.
SymptomMerging split volumes and extracting reports corruption.
CauseA volume was missed in the merge, or the merge order was wrong.
FixConfirm all .part files are present, then merge and extract with cat a.tar.gz.* | tar -xzf -.
Troubleshooting
1List the contents to confirm the structure before deciding how to extract.
tar -tzvf a.tar.gz | head -20Check entries, sizes, and permissions; this is especially the first step for packages of unknown origin.
2Extract to a specified directory with the top level stripped.
mkdir -p /opt/app && tar -xzf a.tar.gz --strip-components=1 -C /opt/appThe standard pattern for deploying a release package, avoiding double nesting.
3Verify the archive is intact.
gzip -t a.tar.gz && echo OKNo output means it is fine; pairing with && echo gives a clear conclusion scripts can act on.
4Exclude unrelated directories before packing.
tar -czvf app.tar.gz --exclude="*.log" --exclude="node_modules/" --exclude=".git" app/Size typically drops by an order of magnitude, and it avoids packing secrets into the archive.
5Use pigz multi-threading for large directories.
tar -czf - /data | pigz > backup.tar.gzMulti-core parallel compression, typically several times faster than single-threaded gzip.
Command Examples
Package a project while excluding logs and dependencies
tar -czvf app.tar.gz --exclude="*.log" --exclude="node_modules/" --exclude=".git" app/--exclude filters at pack time, saving time and disk over packing then deleting. For multi-stage build projects always exclude node_modules — it is usually the bulk of the size and can be rebuilt with npm ci.
Output
app/package.json app/src/ app/src/main.ts app/dist/ app/dist/index.js
Extract into a target directory, stripping the top folder
tar -xzvf package.tar.gz --strip-components=1 -C /opt/app--strip-components=1 removes the first directory level inside the archive and -C sets the destination. Most common when deploying a release package; otherwise you end up with a double structure like /opt/app/package/.
Output
package.json src/ src/main.ts dist/index.js
Inspect an archive before extracting
tar -tzvf package.tar.gz | head -20-t only lists without extracting and -v shows permissions and time. Confirm the path structure and permission bits match expectations before extracting, especially for archives of unknown origin.
Output
-rw-r--r-- root/root 1024 2026-09-28 10:11 package.json drwxr-xr-x root/root 4096 2026-09-28 10:11 src/ -rwxr-xr-x root/root 24576 2026-09-28 10:12 dist/index.js
Package while preserving timestamps
tar -czvf backup-$(date +%F).tar.gz /home/user/
gzip -t backup-$(date +%F).tar.gz && echo OKgzip -t tests integrity; no output means it is fine, and here && echo OK turns that into a clear conclusion. Name files by date to keep multiple backups from overwriting each other.
Output
OK
Common Pitfalls
- tar -x overwrites same-named files without prompting, and paths containing .. or absolute paths can write outside the target — inspect with -t before extracting anything untrusted.
- Without --exclude, tar -c bundles node_modules and .git too, which can multiply the size and leak secrets.
- The flag after -f must match the compression actually used; mismatching -j with a .gz file silently produces the wrong format.
- Appending with tar -r only works on uncompressed .tar — using it on .tar.gz errors out or corrupts the archive.
- After split, every volume must be concatenated with cat archive.* before extracting, or you get a truncated archive.
Tips
- Mnemonic: c=create, x=extract, t=list, z=gzip, j=bzip2, J=xz.
- Before extracting, run tar -tf to inspect contents and confirm there's no ../ path traversal (zip-slip risk).
- For large files, zstd --long=31 uses long-distance matching — 5-10x faster than gzip with better ratio.
- Appending works only on uncompressed .tar; for .tar.gz you must decompress and repackage.
- pigz is the multi-threaded gzip; for large files use tar -cf - dir | pigz > out.tar.gz to speed up greatly.
- Put -C (target dir) after the filename; --strip-components drops the first N directory levels to avoid nested extraction.
FAQ
Which compression format should I use — gzip, bzip2, xz or zstd?
It comes down to speed versus ratio. gzip is fastest with the widest compatibility and is fine for everyday archiving; zstd is close to gzip in speed with a noticeably better ratio and is the better default on modern systems; xz compresses hardest but is slowest, which suits files you archive and rarely reopen; bzip2 is largely obsolete now. The flags are -z, --zstd and -J respectively.
How do I exclude node_modules and logs when creating a tarball?
Use --exclude, for example tar -czvf app.tar.gz --exclude="*.log" --exclude="node_modules/" --exclude="tmp/" app/. Better still, think of it like .gitignore or .dockerignore — clean up before packing, since these files dominate the size and can always be regenerated. Also prefer -C to change directory so the archive does not gain an extra nesting level.
How do I extract without the top-level directory?
Add --strip-components=1: tar -xzvf package.tar.gz --strip-components=1 -C /opt/app. The archive entry app/package.json then lands at /opt/app/package.json instead of /opt/app/app/package.json. This is the standard trick for release tarballs and deploy scripts, usually paired with -C to pick the destination.
How can I inspect an archive without extracting it?
Use -t to list rather than extract: tar -tzvf archive.tar.gz prints names, sizes and permissions without unpacking. Pipe it to search: tar -tf archive.tar.gz | grep "config". And gzip -t archive.tar.gz quickly tests integrity — no output means the archive is fine.
Packing a large directory is slow — how do I speed it up?
Compression is the bottleneck, so use pigz for multi-threaded compression: tar -czf - /data | pigz > backup.tar.gz. It parallelizes across cores and is typically several times faster than single-threaded gzip. If a single file is too big, split it with tar -czf - dir/ | split -b 100M - archive.tar.gz. and reassemble later with cat archive.tar.gz.* | tar -xzvf -.
Official References
Each command links to its official documentation below, so you can verify the latest usage and read deeper.
Maintained by LaoHand
Publicly updated on Jul 21, 2026, continuously proofread against official docs.
Contact Us
Wrong command or description? Send us corrections, business inquiries or product feedback by email.
Contact Us