bzip2(1)

bestie, okay so bzip2(1) is the General Commands Manual page for bzip2 and I'm obsessed ๐Ÿ’œ๐Ÿซถ

๐ŸŒธ NAME ๐ŸŒธ

bzip2, bunzip2 - a block-sorting file compressor, v1.0.8 โœจ bzcat - decompresses files to stdout ๐Ÿฆ‹ bzip2recover - recovers data from damaged bzip2 files ๐Ÿฉน

๐Ÿงš SYNOPSIS ๐Ÿงš

bzip2 [ -cdfkqstvzVL123456789 ] [ filenames ...  ]
bzip2 [ -h|--help ]
bunzip2 [ -fkvsVL ] [ filenames ...  ]
bunzip2 [ -h|--help ]
bzcat [ -s ] [ filenames ...  ]
bzcat [ -h|--help ]
bzip2recover filename

๐ŸŒˆ DESCRIPTION ๐ŸŒˆ

okay so bzip2 compresses files using the Burrows-Wheeler block sorting text compression algorithm, plus Huffman coding ๐Ÿ’… The compression is usually way better than what you get from the more conventional LZ77/LZ78-based compressors, and it gets pretty close to the PPM family of statistical compressors. literally iconic โœจ

the command-line options are deliberately very similar to GNU gzip, but they are not identical, so don't just assume everything works the same ๐Ÿ™ˆ

bzip2 wants a list of file names alongside the command-line flags. each file gets replaced by a compressed version of itself, named original_name.bz2 ๐ŸŽ€ Each compressed file keeps the same modification date, permissions and, when it's possible, ownership as the original, so those properties can be restored properly at decompression time. File name handling is kinda naive, though: there's no mechanism for preserving original file names, permissions, ownerships or dates on filesystems that don't have these concepts, or that have seriously restrictive file name lengths, like MS-DOS ๐Ÿ’€

bzip2 and bunzip2 won't overwrite existing files by default. if you want that to happen, specify the -f flag ๐Ÿ’–

if no file names are given, bzip2 compresses from standard input to standard output. in this case bzip2 will refuse to write compressed output to a terminal, because that would be totally incomprehensible and therefore pointless ๐Ÿ™ƒ

bunzip2 (or bzip2 -d) decompresses all the specified files. Files that weren't created by bzip2 get detected and ignored, and you'll get a warning. bzip2 tries to guess the name of the decompressed file from the compressed one, like this:

filename.bz2    becomes   filename
filename.bz     becomes   filename
filename.tbz2   becomes   filename.tar
filename.tbz    becomes   filename.tar
anyothername    becomes   anyothername.out

if the file doesn't end in one of the recognised endings, .bz2, .bz, .tbz2 or .tbz, bzip2 complains that it can't guess the original name, and it uses the original name with .out appended ๐Ÿ˜ญ

same as compression, supplying no file names means decompression goes from standard input to standard output โœจ

bunzip2 will correctly decompress a file that's the concatenation of two or more compressed files. The result is the concatenation of the matching uncompressed files. Integrity testing (-t) of concatenated compressed files is supported too ๐Ÿซถ

you can also compress or decompress files to standard output with the -c flag. multiple files can be done this way, and the outputs get fed to stdout one after another. Compressing multiple files like this makes a stream with multiple compressed file representations inside it. That stream can only be decompressed correctly by bzip2 version 0.9.0 or later. Earlier versions of bzip2 stop after decompressing the first file in the stream. > that's a whole mood, so be careful with old versions ๐Ÿšจ

bzcat (or bzip2 -dc) decompresses all the specified files to standard output ๐Ÿฆ‹

bzip2 reads arguments from the environment variables BZIP2 and BZIP, in that order, and processes them before any arguments from the command line. this is a super convenient way to set default arguments ๐Ÿ“

compression always happens, even if the compressed file ends up slightly bigger than the original ๐Ÿ™ˆ Files smaller than about one hundred bytes tend to get bigger, since the compression mechanism has a constant overhead in the region of 50 bytes. Random data (including the output of most file compressors) gets coded at about 8.05 bits per byte, which is an expansion of around 0.5%. not the vibe, but it happens ๐Ÿ’€

as a self-check for your protection, bzip2 uses 32-bit CRCs to make sure the decompressed version of a file is identical to the original ๐Ÿ”ฅ This guards against corruption of the compressed data, and against undetected bugs in bzip2 (hopefully very unlikely). The chance of corruption going undetected is microscopic, about one chance in four billion for each file processed. BUT, be aware that the check happens upon decompression, so it can only tell you that something is wrong. It can't help you recover the original uncompressed data. you can use bzip2recover to try recovering data from damaged files ๐Ÿฉน

Return values, bestie: 0 for a normal exit, 1 for environmental problems (file not found, invalid flags, I/O errors, &c), 2 to indicate a corrupt compressed file, and 3 for an internal consistency error (eg, bug) which caused bzip2 to panic ๐Ÿ˜ฑ


okay that's the first half of the page! the OPTIONS section is next and it's giving a whole lot of flags ๐Ÿ‘‘

๐Ÿ’พ MEMORY MANAGEMENT ๐Ÿ’พ

okay so bzip2 compresses big files in blocks ๐Ÿงฑโœจ and the block size changes two things: how small the output gets, and how much memory it eats up while compressing and decompressing. The flags -1 through -9 pick the block size, from 100,000 bytes all the way up to 900,000 bytes. -9 is the default, so you're already getting the biggest one ๐Ÿ’…

When you decompress, bzip2 reads the block size from the header of the compressed file, and bunzip2 gives itself just enough memory to get the job done ๐Ÿซถ Since the block size is stored right inside the compressed file, the -1 to -9 flags don't matter during decompression. They get ignored, bestie ๐Ÿ™ˆ

Here's the estimate for how many bytes compression and decompression need:

Compression:   400 k + ( 8 x block size )

Decompression: 100 k + ( 4 x block size ), or
               100 k + ( 2.5 x block size )

Bigger blocks give you rapidly diminishing marginal returns ๐Ÿ“‰ Most of the compression happens in the first two or three hundred k of block size, which is super useful to remember if you're running bzip2 on a small machine ๐Ÿงš

It's also important to know that the memory you need for decompressing gets locked in at compression time, based on the block size you picked ๐Ÿ”’

For files made with the default 900 k block size, bunzip2 needs about 3700 kbytes to decompress. Now, if you need to decompress any file on a 4 megabyte machine, bunzip2 has an option that uses roughly half that, about 2300 kbytes ๐Ÿฅบ The catch is that decompression speed gets halved too, so only use it when you really have to. That option is -s ๐Ÿ’–

Generally speaking, go with the biggest block size your memory allows, since that gives you the best compression ๐Ÿ† Compression and decompression speed barely change with block size, so that's not something to stress about โœจ

One more thing ๐Ÿ‘€ files that fit inside a single block (which is most files, if you're using a big block size) only touch as much real memory as the file is big. Like, compressing a 20,000 byte file with -9 makes the compressor allocate around 7600 k of memory, but it only actually touches 400 k + 20000 * 8 = 560 kbytes of it. The decompressor allocates 3700 k but only touches 100 k + 20000 * 4 = 180 kbytes ๐Ÿคฏ

Here's a table of the max memory usage for each block size. It also shows the total compressed size for 14 files from the Calgary Text Compression Corpus, which add up to 3,141,622 bytes. That last column gives you a vibe for how compression changes with block size ๐Ÿ“Š Heads up, these numbers kinda undersell the bigger block sizes for bigger files, because the Corpus is mostly made of smaller files ๐Ÿ™ˆ

           Compress   Decompress   Decompress   Corpus
    Flag     usage      usage       -s usage     Size

     -1      1200k       500k         350k      914704
     -2      2000k       900k         600k      877703
     -3      2800k      1300k         850k      860338
     -4      3600k      1700k        1100k      846899
     -5      4400k      2100k        1350k      845160
     -6      5200k      2500k        1600k      838626
     -7      6100k      2900k        1850k      834096
     -8      6800k      3300k        2100k      828642
     -9      7600k      3700k        2350k      828642

๐Ÿงฉ RECOVERING DATA FROM DAMAGED FILES ๐Ÿงฉ

okay this part is a lifesaver ๐Ÿฅน bzip2 compresses files in blocks, usually 900 kbytes long, and every block gets handled on its own ๐Ÿงฑ So if a media or transmission error wrecks a multi-block .bz2 file, you might still be able to save the data from the undamaged blocks ๐Ÿซถ

Each block's compressed form is marked off by a 48-bit pattern, which means you can find the block boundaries with reasonable certainty โœจ Each block also carries its own 32-bit CRC, so damaged blocks can be told apart from the healthy ones ๐Ÿ’…

bzip2recover is a simple program whose whole job is to hunt down the blocks in .bz2 files and write each one into its own .bz2 file ๐Ÿฆ‹ After that, you can run bzip2 -t on the results to check they're intact, then decompress the ones that are undamaged.

bzip2recover takes exactly one argument, the name of the damaged file. It writes a bunch of files called "rec00001file.bz2", "rec00002file.bz2", and so on, each holding one of the extracted blocks ๐Ÿ“ฆ The names are set up so wildcards work in the right order later on. For example, "bzip2 -dc rec*file.bz2 > recovered_data" processes the files in the correct order ๐ŸŽ€

bzip2recover is most useful with big .bz2 files, since those hold lots of blocks. Using it on damaged single-block files is pointless ๐Ÿ™ƒ A damaged block just can't be recovered. And if you want to keep potential data loss from media or transmission errors to a minimum, think about compressing with a smaller block size ๐Ÿ›ก๏ธ


๐Ÿš€ PERFORMANCE NOTES ๐Ÿš€

The sorting phase of compression groups together similar strings in the file ๐Ÿง  Because of that, files with super long runs of repeated symbols, like "aabaabaabaab ..." (repeated several hundred times), can compress more slowly than usual ๐ŸŒ Versions 0.9.5 and above handle this way better than older versions did. The ratio between the worst-case and average-case compression time is around 10:1 ๐Ÿ“‰ For older versions, that figure was more like 100:1, yikes ๐Ÿ˜ญ If you want to watch the progress in extreme detail, you can use the -vvvv option ๐Ÿ‘€

Decompression speed isn't affected by any of this ๐Ÿ’–

bzip2 usually allocates several megabytes of memory to work in, then bounces all over it in a pretty random way ๐ŸŒ€ That means performance, for both compressing and decompressing, mostly comes down to how fast your machine can deal with cache misses. Small code tweaks that cut the miss rate have been seen to give disproportionately big speed boosts ๐Ÿš€ The author's guess is that bzip2 will perform best on machines with very large caches ๐Ÿงš


โš ๏ธ CAVEATS โš ๏ธ

I/O error messages aren't as helpful as they could be ๐Ÿ˜ฉ bzip2 tries really hard to detect I/O errors and exit cleanly, but sometimes the details about what went wrong are kinda misleading.

This manual page is for version 1.0.8 of bzip2 ๐ŸŽ€ Compressed data made by this version is fully forwards and backwards compatible with the earlier public releases: versions 0.1pl2, 0.9.0, 0.9.5, 1.0.0, 1.0.1, 1.0.2 and above. There's one exception though. Versions 0.9.0 and above can correctly decompress multiple concatenated compressed files, but 0.1pl2 can't. It stops after decompressing just the first file in the stream ๐Ÿ™…โ€โ™€๏ธ

Versions of bzip2recover before 1.0.2 used 32-bit integers to represent bit positions in compressed files. That means they couldn't handle compressed files longer than 512 megabytes ๐Ÿ’€ Versions 1.0.2 and above use 64-bit ints on some platforms that support them (GNU supported targets, and Windows). To figure out whether your bzip2recover was built with that limitation, just run it without arguments ๐Ÿ” Either way, you can make yourself an unlimited version by recompiling it with MaybeUInt64 set to be an unsigned 64-bit integer ๐Ÿฆ„


๐Ÿ‘‘ AUTHOR ๐Ÿ‘‘

Written by Julian Seward, jseward@acm.org ๐Ÿ’Œ

The project lives at https://sourceware.org/bzip2/ ๐ŸŒธ

The ideas behind bzip2 come from (at least) a whole crew of people ๐Ÿซถ Michael Burrows and David Wheeler gave us the block sorting transformation, and David Wheeler also did the Huffman coder. Peter Fenwick did the structured coding model in the original bzip, plus lots of refinements. Alistair Moffat, Radford Neal and Ian Witten did the arithmetic coder in the original bzip. The author is super grateful for their help, support and advice ๐Ÿ’– The source distribution's manual points you to documentation sources too ๐Ÿ“š Christian von Roques nudged the author to look for faster sorting algorithms to speed up compression, and Bela Lubkin pushed for better worst-case compression performance ๐Ÿƒโ€โ™€๏ธ Donna Robinson XMLised the documentation ๐Ÿ’ป The bz* scripts are derived from GNU gzip's scripts ๐Ÿงš And many people sent patches, helped with portability problems, lent machines, gave advice, and were just generally helpful ๐Ÿฅฐ


Okay bestie, that's the whole page ๐Ÿ’… It's the bzip2(1) manual, and it's giving main character energy ๐Ÿ‘‘๐Ÿฆ‹