opscape

Archives and compression

gzip

Compress files to .gz (replacing the original by default), or decompress them with -d or gunzip.

gzip [OPTION...] [FILE...]

12 of 12 examples run in Debian 13.7 on 2026-10-31 · gzip 1.13-1+deb13u1 · manual: gzip(1)

gzip FILE compresses one file into FILE.gz and deletes the original, keeping its name, permissions and modification time. gzip -d FILE.gz (or gunzip) reverses it. Each file is compressed separately: gzip has no notion of a directory archive, which is why directories are bundled with tar first and the result is a .tar.gz.

With no file, or with -c, gzip works as a filter between standard input and output, so it slots into pipelines: pg_dump db | gzip > db.sql.gz. To read a compressed file without unpacking it, use zcat (and its relatives zgrep, zless, zdiff).

gzip is fast and readable everywhere, which is why logs, tarballs and HTTP responses use it. zstd compresses about as well while being much faster, and xz compresses better but slower; reach for those when you control both ends.

Examples

Compress a file in place

gzip access.log
ls -l access.log*
output
-rw-rw-r-- 1 dev dev 591 Oct 24 21:55 access.log.gz

access.log is gone, replaced by access.log.gz at about a quarter of the size. The date is the original file's modification time, which gzip carries over.

Keep the original with -k

gzip -k access.log
ls -l access.log*
output
-rw-rw-r-- 1 dev dev 2309 Oct 24 21:55 access.log
-rw-rw-r-- 1 dev dev  591 Oct 24 21:55 access.log.gz

-k (--keep) leaves the input file in place, so both versions exist side by side.

Decompress with -d or gunzip

Setup run before this example
gzip notes.txt
ls notes*
gzip -d notes.txt.gz
ls notes*
output
notes.txt.gz
notes.txt

gzip -d and gunzip are the same thing. The .gz file is replaced by the original notes.txt.

Write to standard output with -c

gzip -c todo.txt > todo.txt.gz
ls todo*
output
todo.txt
todo.txt.gz

-c leaves the input alone and sends the compressed bytes to standard output, so you choose the output name with a redirection. It is also how you compress into another directory.

Show compressed and original sizes

Setup run before this example
gzip -k access.log
gzip -l access.log.gz
explain
output
         compressed        uncompressed  ratio uncompressed_name
                591                2309  75.7% access.log

-l reads the sizes from the file's trailer without decompressing it. The ratio is the space saved: 75.7% here. The stored size is modulo 4 GiB, so it is wrong for larger files.

Report the saving per file

gzip -v data/sales.csv data/users.csv
explain
output
data/sales.csv:	 61.7% -- replaced with data/sales.csv.gz
data/users.csv:	 43.6% -- replaced with data/users.csv.gz

-v prints, for each file, the percentage saved and what it was replaced with.

Trade speed for size with -1 to -9

gzip -1 -c access.log | wc -c
gzip -9 -c access.log | wc -c
output
658
591

-1 is fastest, -9 compresses best, and the default is -6. Here -9 saves about 10% over -1; on large files it also costs noticeably more time, for a few percent over the default.

Compress the output of a command

grep ' 404 ' access.log | gzip > not-found.log.gz
zcat not-found.log.gz | wc -l
output
4

With no file name gzip reads standard input and writes standard output. zcat reads it back to check: the four matching lines survived the trip.

Compress every file in a directory tree

gzip -r logs
ls logs
output
app.log.1.gz
app.log.gz
error.log.gz

-r walks into the directory and compresses each file separately. The directory itself is not archived: for one file containing a whole tree, use tar -czf.

Concatenated gzip files are still valid

gzip -c todo.txt > all.gz
gzip -c data/poem.txt >> all.gz
zcat all.gz
output
buy milk
fix login bug
write tests
fix logout bug
deploy v2.4
The quick brown fox
jumps over the lazy dog.
The dog sleeps;
the fox runs on.

A gzip file may hold several compressed members one after another, and decompression joins them. That is why appending to a .gz log with >> works.

Check that a file is intact

Setup run before this example
gzip -k access.log
head -c 300 access.log.gz > cut.gz
gzip -t access.log.gz && echo "access.log.gz is fine"
gzip -t cut.gz
outputexit 1
access.log.gz is fine

gzip: cut.gz: unexpected end of file

-t decompresses in memory and checks the CRC without writing anything. The truncated copy fails with unexpected end of file and exit status 1.

gzip will not overwrite an existing file

Setup run before this example
gzip -k notes.txt
gzip -d notes.txt.gz
explain
outputexit 2
gzip: notes.txt already exists;	not overwritten

notes.txt is still there (the .gz was made with -k). In a script, gzip refuses with exit status 2 instead of clobbering it; at a terminal it asks first. -f forces the overwrite.

Common pitfalls

  • Plain gzip file deletes file. Use -k or -c when you need to keep the original.

  • gzip dir does nothing useful (it skips directories with a warning), and gzip -r dir produces a pile of separate .gz files. Archive a directory with tar -czf dir.tar.gz dir.

  • gzip -l gets the original size from a 32-bit field, so it shows the size modulo 4 GiB. For big files, zcat file.gz | wc -c is the reliable count.

  • gzip -c a b > out.gz produces one file with two members; decompressing gives a and b joined, not two files.

GNU vs BSD and macOS

The examples above ran the GNU/Linux version. These are the differences that matter on macOS and the BSDs (written from their documentation, not run here).

  • macOS and FreeBSD ship their own gzip with the same everyday options (-c -d -k -l -r -t -v -1..-9). Older versions lacked -k; gzip -c f > f.gz works everywhere.

Options worth knowing

A selection, described in our own words. For the full list, see gzip(1) or gzip --help.

OptionWhat it does
-c, --stdoutWrite to standard output and keep the input files.
-d, --decompressDecompress instead of compress.
-k, --keepKeep the input files instead of deleting them.
-f, --forceOverwrite existing output files and compress links or already-compressed names.
-l, --listShow compressed size, original size and ratio of .gz files.
-r, --recursiveCompress or decompress every file inside the named directories.
-t, --testCheck the integrity of compressed files without writing output.
-v, --verbosePrint the name and saving for each file.
-q, --quietSuppress warnings.
-n, --no-nameDo not store the original name and timestamp (when compressing).
-N, --nameStore or restore the original name and timestamp.
-S, --suffix SUFUse SUF instead of .gz.
-1, --fastCompress fastest, with the least compression.
-9, --bestCompress best, most slowly.
--rsyncableMake output that rsync can transfer efficiently after small changes.

Related