compress Command in Linux: Complete Guide to File Compression Utility and Parameters

compress command in Linux and it perimeters

I think of compress as a piece of Unix history I still need to know how to handle rather than a tool I’d reach for on a new project. It was the original standard Unix compression utility, long before gzip existed, and every so often I still run into a .Z file in some old archive or legacy backup system that requires it. Let me walk through everything about compress — how it works, why it was eventually displaced, and what to know if you ever need to use it today.

What compress Does

compress reduces file size using the LZW (Lempel-Ziv-Welch) compression algorithm, producing an output file with a .Z extension. By default it replaces the original file with the compressed version, similar to how gzip behaves by default.

On modern Linux distributions, compress is provided by the ncompress package, since it’s no longer part of the base system on most distros. I confirmed this directly — on a fresh Ubuntu container, compress wasn’t available at all until I installed it:

$ which compress uncompress
/usr/bin/uncompress
$ apt-get install -y ncompress
...
Setting up ncompress (5.0-1) ...
$ which compress
/usr/bin/compress

Interestingly, uncompress was already present before installing ncompress, because GNU gzip ships a compatibility wrapper script for decompressing .Z files even without the real LZW implementation installed — but compress (the compression direction) genuinely requires the dedicated package.

Basic Syntax

compress [options] file [file2 ...]

Testing It in Practice

$ cp sample.txt compresstest.txt
$ compress compresstest.txt
$ ls -la compresstest.txt.Z
-rw-r--r-- 1 root root 584 compresstest.txt.Z

The original 2226-byte file compressed down to 584 bytes — roughly a 74% reduction, which is a decent ratio for LZW on reasonably repetitive text, though it’s still noticeably worse than what gzip -9 would achieve on the same data.

Parameters and Options

OptionDescription
-cWrite compressed output to stdout, leaving the original file untouched
-fForce compression, overwriting existing output files without prompting
-vVerbose; print the compression percentage achieved
-dDecompress instead of compress (equivalent to running uncompress)
-rRecursively compress files within directories
-b <bits>Set the maximum number of bits used for LZW codes (historically tunable, default is usually 16)

The -b flag is a genuinely interesting historical artifact: LZW’s dictionary size is bounded by the code width you allow, and older systems with limited memory sometimes needed a smaller code width (fewer bits) to keep the running dictionary compact, at the cost of somewhat worse compression.

How compress Works Internally

LZW builds a dictionary of byte sequences incrementally as it scans through input data. Here’s the conceptual process:

  1. Start with a dictionary containing every single byte value (256 entries for 0–255).
  2. Scan the input, looking for the longest sequence already in the dictionary.
  3. Output the dictionary code for that sequence.
  4. Add a new entry to the dictionary: the matched sequence plus the next byte.
  5. Continue from the next unmatched byte.

The elegant part is that the decompressor doesn’t need the dictionary transmitted alongside the data — it rebuilds an identical dictionary on the fly, using the same deterministic rule, purely from the sequence of codes it receives. This is different from gzip‘s DEFLATE, which explicitly encodes Huffman tables as part of the compressed stream.

.Z files start with a fixed two-byte magic number, 0x1F 0x9D, followed by a byte encoding the maximum code width in use, then the LZW-coded data itself.

Why compress Was Replaced by gzip

This is worth understanding because it explains a real piece of free software history. LZW was covered by a patent held by Unisys, and in the late 1980s and into the 1990s, Unisys began enforcing licensing terms around LZW use — famously affecting the GIF image format as well, which also used LZW. This created real uncertainty around freely distributing software that used compress.

In response, the GNU project developed gzip, built on the DEFLATE algorithm (LZ77 plus Huffman coding), which avoided the patent issue entirely and, as a bonus, generally compressed better than classic compress. By the mid-1990s, gzip had essentially replaced compress as the default Unix/Linux compression tool, and that’s the state of things today — the LZW patents have long since expired, but gzip had already won on technical merit as well by that point.

Real-World Use Cases

Maintaining compatibility with legacy Unix systems. If you’re dealing with an older Solaris, HP-UX, or AIX environment (or software distributed for one), you may specifically need .Z format output rather than .gz, since some ancient scripts or tools expect it.

Recompressing old archives for consistency if you’ve inherited a mixed collection of .Z and .gz files and want to standardize:

for f in *.Z; do
  uncompress -c "$f" | gzip -9 > "${f%.Z}.gz" && rm "$f"
done

I’ve used a variant of this exact loop when consolidating old backup directories that had accumulated files compressed with several different tools over the years.

Testing understanding of Unix compression history — admittedly more of an educational use case today, but genuinely useful context for understanding why .gz, .bz2, .xz, and .zst all exist as separate, sequential “better than the last” replacements in Unix history.

compress vs gzip vs modern alternatives

ToolAlgorithmTypical RatioSpeedStatus Today
compressLZWLowest of the groupFastLegacy, rarely used for new work
gzipDEFLATE (LZ77 + Huffman)ModerateFastStill the universal default
bzip2Burrows-Wheeler + HuffmanBetter than gzip on many text filesSlowerDeclining in popularity
xzLZMA2Best ratio of the classic toolsSlow to compressCommon for release tarballs
zstdCustom, tunableCompetitive with xzFast, multi-threadedIncreasingly the modern default

If I ever need to produce a .Z file today, it’s exclusively for compatibility with something old that explicitly demands that exact format — never for genuinely optimizing storage or transfer.

Troubleshooting Common Problems

“compress: command not found” — the package simply isn’t installed on most modern distributions by default:

# Debian/Ubuntu
sudo apt-get install ncompress

# RHEL/CentOS/Fedora
sudo dnf install ncompress

“compresstest.txt.Z already exists” — same overwrite-protection behavior you’d see in gzip; use -f to force it.

Poor compression ratio compared to expectations — this is simply LZW being weaker than modern algorithms on most real-world data; it’s not a configuration problem, it’s an inherent algorithmic limitation. If ratio matters, use gzip, xz, or zstd instead unless format compatibility with .Z specifically is required.

Confusing -b bit-width behavior — most modern uses never need to touch this flag; it exists almost entirely for compatibility with historical systems that had constrained memory, and adjusting it on modern hardware provides no meaningful benefit.

Performance Considerations

LZW compression is computationally lightweight, which made sense for the era it was designed in — hardware in the 1980s couldn’t afford heavier algorithms. On modern hardware, this speed advantage is essentially irrelevant, since gzip and even zstd at fast presets are plenty quick and produce meaningfully smaller output. There’s essentially no scenario on contemporary systems where compress‘s speed advantage over gzip matters enough to offset its worse compression ratio.

Security Implications

There are no significant unique security concerns tied specifically to the compress algorithm itself, but as with any decompression path, I’d be cautious feeding .Z files from untrusted sources into uncompress without first considering decompression-bomb-style risks (a small compressed file expanding to something enormous). The ncompress codebase is small and mature, but it’s also not something that receives much modern security scrutiny compared to widely-audited tools like gzip or zstd, simply because usage has dropped so dramatically.

Compatibility Across Distributions

ncompress (providing both compress and uncompress) is packaged consistently across Debian, Ubuntu, RHEL/CentOS/Fedora, openSUSE, and Arch, so installing it when needed is straightforward everywhere. The .Z format itself, being a decades-old, stable, and simple specification, decompresses identically regardless of which Unix or Linux flavor produced the original file.

Inspecting a .Z File’s Header Manually

Since .Z files have such a simple, fixed structure, it’s genuinely instructive to look at the raw header bytes with a hex viewer:

$ xxd compresstest.txt.Z | head -1
00000000: 1f9d 90c8 6465 20a0 1030 8144 0208 1c48  ....de .0.D...H

The first two bytes, 1f 9d, are the fixed LZW magic number I mentioned earlier — you’ll see this exact byte pair at the start of every valid .Z file, regardless of what tool or system produced it. The third byte encodes flags including the maximum code width, which tells the decompressor how many bits wide each LZW code in the stream is. Recognizing this magic number is genuinely useful troubleshooting knowledge — if a file claims a .Z extension but doesn’t start with these two bytes, you know immediately it’s either corrupted or mislabeled.

Scripting Around compress in Legacy Data Pipelines

If you maintain any pipeline that has to interoperate with an older system still producing .Z files — I’ve seen this in some long-lived scientific computing and financial data-processing environments — a defensive script pattern helps avoid surprises:

#!/bin/bash
for f in "$@"; do
  if [[ "$(xxd -p -l2 "$f")" == "1f9d" ]]; then
    echo "Valid .Z file: $f"
    uncompress -c "$f" > "${f%.Z}.decoded"
  else
    echo "Not a valid .Z file, skipping: $f" >&2
  fi
done

This kind of defensive check matters more with compress/.Z files specifically than with gzip, simply because .Z files are rarer today and more likely to have been mislabeled or corrupted somewhere along an old, poorly documented data pipeline.

Interoperability With Other Unix Systems

If you’re bridging a modern Linux box with an older Solaris, AIX, or HP-UX machine that still defaults to compress for some administrative task, it’s worth confirming both ends agree on maximum code width. Some very old implementations only supported 12-bit or 13-bit codes by default, while GNU’s ncompress defaults to a wider 16-bit code table. Mismatched expectations here are rare in practice since uncompress reads the code width from the file header itself rather than assuming a fixed value, but it’s a detail worth knowing if you ever see “not enough magic” or code-width-related errors when moving .Z files between genuinely old and new systems.

Understanding compress’s Adaptive Ratio Behavior

One characteristic worth knowing about LZW-based compress, distinct from DEFLATE-based tools: its compression ratio tends to improve as it processes more of a file, because the dictionary accumulates more useful repeated sequences the further into the data it gets. This means very short files often compress noticeably worse (proportionally) than long files with the same general content characteristics, since there simply isn’t enough data for the dictionary to build up a rich set of useful back-references before the file ends. I’ve seen this concretely when compressing many small configuration snippets individually versus concatenating them into one larger file first and compressing that — the concatenated version compresses meaningfully better per byte, purely because of this dictionary-warm-up effect.

# Compressing many small files separately
for f in configs/*.conf; do compress -c "$f" > "$f.Z"; done

# vs. concatenating first, then compressing once
cat configs/*.conf | compress -c > all-configs.Z

The second approach produces a smaller total output in most realistic cases, though obviously at the cost of losing individual file boundaries unless you also record file lengths or delimiters separately.

compress’s Place in the Broader Unix Compression Timeline

It’s worth situating compress in its proper historical context: it was standardized as part of Unix System V and BSD in the early-to-mid 1980s, becoming the de facto standard compression tool for roughly a decade before gzip‘s 1992 release began displacing it. During that transitional period through the mid-1990s, it wasn’t uncommon to see both formats supported side by side in software distributions, precisely because not every system had gzip installed yet while compress was still nearly universal. That transitional period is long over today, but understanding it explains why so many older Unix man pages, RFCs, and technical documents from that era reference .Z files as the assumed default compression format, even though virtually nothing produces them by default anymore.

Summary

compress was the compression tool everyone used before gzip took over, and understanding it gives useful context for why the Unix compression landscape evolved the way it did — patent concerns pushing the free software world toward better, unencumbered algorithms that also happened to compress better. Today, I’d only reach for compress to interoperate with something genuinely old that specifically expects .Z format; for everything else, gzip, xz, or zstd are the better choice on every axis that matters.

References

  • GNU Gzip Manual (background on why gzip replaced compress): https://www.gnu.org/software/gzip/manual/gzip.html
  • man compress / man uncompress
  • ncompress project, packaged in all major distribution repositories
Total
1
Shares

Leave a Reply

Previous Post
zless command in Linux and it perimeters

zless Command in Linux: Complete Guide to Viewing Compressed Files and Parameters

Next Post
cpio command in Linux and it perimeters

cpio Command in Linux: Complete Guide to Copy In/Out File Archiving and Parameters

Related Posts