Read bzip2 Files Safely with bzmore and bzless
bzmore and bzless page through bzip2-compressed text a screen at a time, and leave the original file completely untouched. You can also search within it and move between several files. The installed bzip2 package is version 1.0.8-5.1ubuntu0.1 on this machine. Allow about ten minutes for the first pass. You need a shell, a readable text or .bz2 file, and a terminal if you want the interactive pager controls.
The route
Jump straight to the step you need, or tick off Done means at the end.
This guide uses bzmore. The installed manual describes bzless as an equivalent name, and the wrapper selects the corresponding pager when invoked through that name. Neither command decompresses a file in place.
1. Check the commands and choose the pager
Confirm which executable your shell will run:
$ command -v bzmore
/home/linuxbrew/.linuxbrew/bin/bzmore
$ command -v bzless
/home/linuxbrew/.linuxbrew/bin/bzless
Use bzmore when you want the traditional more-style interface. Use bzless when the installed less pager is your normal preference. Both accept file names rather than a compression option.
Checkpoint
If either command is missing, stop here and use your normal package-management process to install bzip2. Do not replace a missing command with a guessed option or run the reader as root.
2. Open a compressed or plain file
Pass a compressed file directly:
$ bzmore /path/to/report.txt.bz2
On a terminal, the reader pauses after each screenful with a --More-- prompt. On a 24-line terminal, the documented default window is 22 lines. Press the space bar for another screenful, or press Return for one more line.
The command also reads an ordinary uncompressed file:
$ bzmore /path/to/report.txt
If the exact name does not exist, bzmore tries the same name with .bz2 appended. Convenient for a logical name such as /path/to/report.txt, but it can hide a spelling mistake if you do not check the path first:
$ test -r /path/to/report.txt && echo readable || echo 'check the file name'
3. Move through the current file
The pager commands take effect immediately, so they do not need a final Return. The most useful controls:
- Space shows another screenful; type a number first to display that many more lines.
- Return shows one additional line.
- d or Control-D scrolls 11 lines; type a number before Control-D to set that scroll size.
- A number then z displays a screenful and temporarily sets the window size to that number of lines.
- A number then s skips that many lines, then displays a screenful.
- A number then f skips that many screenfuls, then displays one.
- = displays the current line number.
The size set with z returns to the default when the current file ends. If output is running too quickly, the manual documents Control-Backslash as the quit key, which normally stops output and returns to the prompt; some output already waiting in the terminal may be lost.
4. Search without extracting the file
At the prompt, type a slash followed by a regular expression:
/ERROR
The reader shows a screenful beginning two lines before the matching location. Add a number before the slash to search for that occurrence, such as 2/timeout. Press n to repeat the last search, or prefix it with a number to find a later occurrence. If no match is found, the reader moves on to the next file when one is queued.
Search input uses your terminal's erase and line-kill characters, and erasing back past the first column cancels the search. Remember that the pattern is a regular expression, not necessarily a literal string: characters such as . can match more than one character.
5. Read several files and control the boundary
Give several names in one command:
$ bzmore /path/to/january.txt.bz2 /path/to/february.txt.bz2
When the next-file prompt appears, press q or Q to stop the current file and continue with the next one. At that boundary, e or q exits the reader, while s skips the next file. The two uses of q are context-sensitive, so read the prompt before pressing it.
Security boundary
Press . to repeat the previous pager command. The ! command runs a shell command while paused, with an exclamation mark standing for the previous shell command; it executes with your account's normal shell permissions. Do not paste untrusted text into it, and do not use it to modify or delete files while you are only trying to read an archive.
6. Use a pipe when interactivity is not needed
When standard output is not a terminal, bzmore behaves like bzcat and prints a header before each named file. Useful for a quick capture, but it is not a clean data stream for a script that expects only the decompressed text:
$ bzmore /path/to/report.txt.bz2 > /tmp/report-view.txt
$ sed -n '1,5p' /tmp/report-view.txt
For a script or a pipeline that needs decompressed bytes without the pager's file header, use the decompressor directly instead:
$ bzip2 -cd /path/to/report.txt.bz2 | sed -n '1,20p'
That command only reads the source. Redirection with > does create or truncate its destination, so use a new temporary path when the output matters; do not overwrite the compressed input with a redirected command.
Common traps
Contents look wrong. Check whether the file is really bzip2 data and whether decompression succeeds:
$ file /path/to/report.txt.bz2
$ bzip2 -t /path/to/report.txt.bz2
$ printf 'status=%s\n' "$?"
A status of zero from bzip2 -t means the integrity test completed successfully. A missing file, an unreadable path, or a damaged archive needs fixing at the file or storage layer; bzmore does not repair it. If interactive controls do not respond, make sure you are running it in a terminal rather than feeding it to a non-interactive job.
Done means
- You can open both
.bz2and plain text withbzmoreorbzless. - You know the space, Return, search, line-number and file-boundary controls.
- You check ambiguous paths before relying on the automatic
.bz2fallback. - You use
bzip2 -cdrather than a pager when a pipeline needs unadorned decompressed text. - You have not modified the source archive, and you treat the
!prompt as an ordinary shell with real account permissions.