bzgrep Command in Linux: Search .bz2 Files

Search compressed logs without unpacking them, learn when bzgrep should hand off to find or tar, and handle wrapper quirks such as missing aliases, -H labels, recursive searches, and bad .bz2 data.

PublishedAuthorJoshua JamesRead time7 minGuide typeLinux Commands

Compressed log rotations are useful until you need to search them during an outage or audit. The bzgrep command in Linux searches the decompressed text inside .bz2 files without extracting copies first, which keeps old logs, exports, and support bundles in place while you look for the exact lines that matter.

bzgrep is a wrapper from the bzip2 package that feeds bzip2-compressed input into grep. The companion names bzegrep and bzfgrep exist on many systems, but new commands and scripts are cleaner when they use bzgrep -E for extended regular expressions and bzgrep -F for fixed-string searches.

Use bzgrep Syntax and Pattern Modes

bzgrep accepts a search pattern, optional grep flags, and one or more files. It can read bzip2-compressed files and plain text files, but its main value is searching .bz2 data without a separate bunzip2 decompression step.

bzgrep [grep_options] PATTERN [FILE...]
bzgrep -E [grep_options] PATTERN [FILE...]
bzgrep -F [grep_options] PATTERN [FILE...]
NeedPreferred Command FormWhat It Means
Basic regular expression searchbzgrep 'timeout' app.log.bz2Uses the default grep pattern mode.
Extended regular expressionsbzgrep -E 'WARN|ERROR' app.log.bz2Uses grep -E style alternation, grouping, and repetition.
Fixed-string matchingbzgrep -F 'literal [cache.*]' app.log.bz2Treats regex metacharacters as ordinary text.
Legacy extended shortcutbzegrep 'WARN|ERROR' app.log.bz2Compatibility name for extended matching where the command exists.
Legacy fixed shortcutbzfgrep 'literal [cache.*]' app.log.bz2Compatibility name for fixed-string matching where the command exists.
Quiet script checkbzgrep -q 'ERROR' app.log.bz2Returns status only, with no matching lines printed.
List matching filesbzgrep -l 'ERROR' *.bz2Prints compressed filenames that contain at least one match.

Treat bzegrep and bzfgrep as compatibility names. GNU grep marks egrep and fgrep as obsolescent, and some Arch-family systems provide bzgrep without those alias commands. Use bzgrep -E and bzgrep -F when you want commands that are easier to maintain.

The official bzip2 manual explains the bzip2 file format and companion tools, while the GNU grep manual documents pattern modes, options, and exit status behavior. For broader pattern examples on uncompressed text, use the grep command examples as the matching reference.

Install or Verify bzgrep on Linux

The package name is bzip2, not bzgrep. Many desktop systems already include it, while minimal servers and containers may need the package installed before bzgrep, the bzcat command, and the bzip2 command appear in $PATH.

Check the main command and compressor first:

command -v bzgrep bzip2

A normal installed system prints paths similar to:

/usr/bin/bzgrep
/usr/bin/bzip2

Check the compatibility command names separately when you plan to run older examples:

command -v bzegrep bzfgrep

If that check prints nothing for one or both names, keep using bzgrep -E and bzgrep -F. The missing aliases do not mean the main wrapper is broken.

Install bzgrep on Ubuntu or Debian Systems

Install the bzip2 package with APT when bzgrep is missing:

sudo apt update
sudo apt install bzip2

Install bzgrep on Fedora or RHEL-Family Systems

Fedora, Rocky Linux, AlmaLinux, CentOS Stream, and related DNF systems use the same package name:

sudo dnf install bzip2

Install bzgrep on Arch Linux or Manjaro

Sync package metadata and upgrade before installing the package on Arch-family systems so the install does not create a partial-upgrade state:

sudo pacman -Syu bzip2

Install bzgrep on openSUSE

Use zypper on openSUSE Leap or Tumbleweed:

sudo zypper install bzip2

After installation, repeat command -v bzgrep bzip2. Package-manager updates handle this utility with the rest of the system; no separate upstream update flow is needed for normal distro packages.

Create a bzgrep Practice Directory

A disposable directory keeps the examples repeatable. The setup recreates ~/bzgrep-demo, so move anything you want to keep out of that path before running it. It then adds two compressed log files, one nested compressed log for recursive examples, and one compressed tar archive for the archive-boundary section.

The setup command permanently deletes any existing ~/bzgrep-demo directory before recreating it. Check the path first if you have reused that directory name for real files.

rm -rf -- ~/bzgrep-demo
mkdir -p ~/bzgrep-demo
cd ~/bzgrep-demo

cat > app.log <<'EOF'
INFO service started
WARN cache warmup delayed
ERROR connection timeout
INFO retry scheduled
ERROR database timeout
--flag enabled
literal [cache.*]
EOF

cat > rotated.log <<'EOF'
INFO old service started
ERROR old disk warning
EOF

mkdir -p archive/nested tar-demo/logs
cat > archive/nested/worker.log <<'EOF'
ERROR nested worker failed
EOF

cat > tar-demo/logs/app.log <<'EOF'
INFO archived start
ERROR archived failure
EOF

bzip2 -k app.log rotated.log archive/nested/worker.log
tar -cjf logs.tar.bz2 -C tar-demo logs
ls -1 *.bz2

The top-level directory now contains two searchable bzip2 files and one compressed tar archive:

app.log.bz2
logs.tar.bz2
rotated.log.bz2

Search bzip2 Logs with bzgrep

Start with line-numbered searches when you need to jump from a match back to the original text after extraction or review.

Find Matching Lines in One Compressed File

Search one compressed log for error lines and print line numbers with -n:

bzgrep -n 'ERROR' app.log.bz2
3:ERROR connection timeout
5:ERROR database timeout

The compressed file remains unchanged. bzgrep streams decompressed content to grep and prints the matching lines. Use bzless to review the compressed log interactively when the match needs surrounding context.

Search Multiple Compressed Files

Give multiple filenames when you want file prefixes on matching lines:

bzgrep -n 'ERROR' app.log.bz2 rotated.log.bz2
app.log.bz2:3:ERROR connection timeout
app.log.bz2:5:ERROR database timeout
rotated.log.bz2:2:ERROR old disk warning

Avoid adding -H by habit. Some bzgrep wrappers feed each file to grep through standard input, so -H can produce labels such as (standard input). Multiple file operands and -l give cleaner filename output.

Search Without Case Sensitivity

Use -i when log levels or messages may use mixed case:

bzgrep -in 'error' app.log.bz2
3:ERROR connection timeout
5:ERROR database timeout

Count Matches in a Compressed File

Use -c when a count is enough for a quick check or script branch:

bzgrep -c 'ERROR' app.log.bz2
2

List Files That Contain a Match

Use -l when you only need the compressed filenames that contain the pattern:

bzgrep -l 'ERROR' app.log.bz2 rotated.log.bz2
app.log.bz2
rotated.log.bz2

Print Context Around a Match

Use -C to see lines around a match. This is useful when an error line needs the preceding warning or following retry state:

bzgrep -C1 'connection timeout' app.log.bz2
WARN cache warmup delayed
ERROR connection timeout
INFO retry scheduled

Use Extended and Fixed-String Matching

bzgrep follows grep pattern rules after decompression. Choose the pattern mode deliberately so metacharacters mean what you expect.

Search with Extended Regular Expressions

Use -E for extended regular expressions such as alternation with |:

bzgrep -En 'WARN|ERROR' app.log.bz2
2:WARN cache warmup delayed
3:ERROR connection timeout
5:ERROR database timeout

bzegrep -n 'WARN|ERROR' app.log.bz2 is the older compatibility form. Prefer bzgrep -E in new examples because it does not depend on the separate bzegrep command name.

Search for Literal Text with Fixed Strings

Use -F when characters such as [, ], ., and * should match literally instead of acting like regex syntax:

bzgrep -Fn 'literal [cache.*]' app.log.bz2
7:literal [cache.*]

bzfgrep -n 'literal [cache.*]' app.log.bz2 is the older compatibility form. Prefer bzgrep -F when you want a fixed-string search that works even when bzfgrep is not installed.

Search for Patterns That Start with a Hyphen

Use -e when the pattern itself starts with -. Some bzgrep wrappers switch through egrep internally for -e and -f, so pinning GREP to the real grep path keeps GNU grep 3.8 and newer from printing an obsolescence warning:

GREP=$(command -v grep) bzgrep -n -e '--flag' app.log.bz2
6:--flag enabled

Search Trees of bzip2 Files Safely

Do not rely on bzgrep -r to find compressed logs recursively. Wrapper behavior differs: some Debian-family wrappers reject recursive option bundles such as -rn, while Fedora, Rocky Linux, Manjaro, and openSUSE wrappers can pass recursion through to grep and search plain files too. Select regular .bz2 files first, exclude compressed tar archives, then run bzgrep on the remaining files.

List compressed files under the current directory that contain errors:

find . -type f -name '*.bz2' ! -name '*.tar.bz2' ! -name '*.tbz2' ! -name '*.tbz' -exec bzgrep -l 'ERROR' {} + | sort
./app.log.bz2
./archive/nested/worker.log.bz2
./rotated.log.bz2

Print matching lines from the same file set when you need line numbers:

find . -type f -name '*.bz2' ! -name '*.tar.bz2' ! -name '*.tbz2' ! -name '*.tbz' -exec bzgrep -n 'ERROR' {} + | sort
./app.log.bz2:3:ERROR connection timeout
./app.log.bz2:5:ERROR database timeout
./archive/nested/worker.log.bz2:1:ERROR nested worker failed
./rotated.log.bz2:2:ERROR old disk warning

The find -exec command pattern owns the recursive file selection, and bzgrep only searches regular compressed files. That split avoids directory noise and prevents plain log copies from being mixed into a compressed-log review.

Handle tar.bz2 Archives Correctly

A .tar.bz2 file is a tar archive compressed as one bzip2 stream. bzgrep can notice that a pattern exists somewhere inside the decompressed tar bytes, but it does not understand tar member names. That is why a direct search can produce a binary-match message instead of a useful log line:

bzgrep -n 'ERROR' logs.tar.bz2
grep: (standard input): binary file matches

Older grep builds can word the same result as Binary file (standard input) matches. Either message means the search reached tar container bytes, not a readable log member.

List the archive members first, then stream the target member to grep with tar:

tar -tjf logs.tar.bz2
logs/
logs/app.log
tar -xOjf logs.tar.bz2 logs/app.log | grep -n 'ERROR'
2:ERROR archived failure

Use the tar command guide when you need broader archive listing, extraction, or path-control examples. If the file is gzip-compressed instead of bzip2-compressed, use zgrep and the gzip command examples rather than forcing a bzip2 wrapper onto the wrong format.

Use bzgrep Exit Status in Scripts

bzgrep follows grep exit status conventions after decompression: status 0 means at least one match, status 1 means no match, and status 2 or another higher value means a real error. Handle the no-match case deliberately instead of treating every nonzero status as a failure.

if bzgrep -q 'ERROR' app.log.bz2; then
    echo 'Errors found'
else
    status=$?
    if [ "$status" -eq 1 ]; then
        echo 'No errors found'
    else
        echo 'Search failed' >&2
        exit "$status"
    fi
fi
Errors found

This pattern is safer than chaining bzgrep -q ... && next-command inside larger scripts because a no-match result is a normal search outcome, not a broken archive or command failure.

Troubleshoot Common bzgrep Problems

Most bzgrep problems come from a missing bzip2 package, legacy alias names, wrapper filename labels, recursive search expectations, tar archives, or invalid compressed data.

Fix bzgrep Command Not Found

Check the command path before changing scripts or aliases:

command -v bzgrep || echo 'bzgrep is missing'

Install bzip2 with the package-manager command for your distribution, then repeat command -v bzgrep bzip2. On minimal systems, the package can be absent even when grep is installed.

Fix Missing bzegrep or bzfgrep Commands

If bzegrep or bzfgrep is missing, use the equivalent bzgrep option instead:

bzgrep -E 'WARN|ERROR' app.log.bz2
bzgrep -F 'literal [cache.*]' app.log.bz2

If a legacy command prints an egrep is obsolescent or fgrep is obsolescent warning, update the command to bzgrep -E or bzgrep -F. The warning comes from modern grep, not from a damaged .bz2 file.

Fix Standard Input Filename Labels

Some wrappers show (standard input) when -H is used because each compressed file is decompressed through a pipe before grep sees it. Ubuntu’s wrapper can print normal filename labels here, but Fedora, Rocky Linux, Manjaro, and openSUSE can show this symptom:

bzgrep -Hn 'ERROR' app.log.bz2 rotated.log.bz2
app.log.bz2:(standard input):3:ERROR connection timeout
app.log.bz2:(standard input):5:ERROR database timeout
rotated.log.bz2:(standard input):2:ERROR old disk warning

Remove -H and pass more than one file when you need normal filename prefixes, or use -l when filenames alone are enough.

bzgrep -n 'ERROR' app.log.bz2 rotated.log.bz2
bzgrep -l 'ERROR' app.log.bz2 rotated.log.bz2

Fix Recursive Searches That Hit Plain Files

If bzgrep -r fails or searches plain log files, the wrapper is not giving you a clean recursive compressed-file search. Start by reproducing the behavior with combined output:

bzgrep -rn 'ERROR' . 2>&1 | sort

Debian-family wrappers can stop with an unsupported-option error:

/usr/bin/bzgrep: -rn: option not supported

Other wrappers may recurse through plain files and report the directory that bzip2 cannot read:

app.log:3:ERROR connection timeout
app.log:5:ERROR database timeout
archive/nested/worker.log:1:ERROR nested worker failed
bzip2: Input file . is a directory.
rotated.log:2:ERROR old disk warning
tar-demo/logs/app.log:2:ERROR archived failure

Move recursion to find, filter for regular .bz2 files, and skip compressed tar archives:

find . -type f -name '*.bz2' ! -name '*.tar.bz2' ! -name '*.tbz2' ! -name '*.tbz' -exec bzgrep -l 'ERROR' {} + | sort
./app.log.bz2
./archive/nested/worker.log.bz2
./rotated.log.bz2

Fix Binary Matches from tar.bz2 Files

If bzgrep reports that standard input is a binary file when searching .tar.bz2 data, inspect the tar archive instead of searching the whole tar stream. For comparing two bzip2-compressed files rather than searching inside them, use the bzdiff command examples.

bzgrep -n 'ERROR' logs.tar.bz2
grep: (standard input): binary file matches
tar -tjf logs.tar.bz2
tar -xOjf logs.tar.bz2 logs/app.log | grep -n 'ERROR'
logs/
logs/app.log
2:ERROR archived failure

Test Suspect bzip2 Data Before Searching

A filename ending in .bz2 is not proof that the content is valid bzip2 data. Test an unknown file before trusting a quiet no-match result:

printf 'not bzip2 data\n' > bad.bz2
bzip2 -t bad.bz2
bzip2: bad.bz2: bad magic number (file not created by bzip2)

You can use the `bzip2recover' program to attempt to recover
data from undamaged sections of corrupted files.

Use a fresh copy when the test fails. If the file is a damaged but important bzip2 archive, work in a clean directory and inspect any bzip2recover output before using recovered pieces in scripts.

Clean Up the bzgrep Demo Directory

Remove the practice directory when you no longer need the sample logs and archive:

This command permanently deletes the disposable ~/bzgrep-demo directory and everything inside it. Check the path before running it if you adapted the examples for real data.

cd ~
rm -rf -- ~/bzgrep-demo

Conclusion

bzgrep is ready for compressed-log searches when you can choose basic, extended, and fixed-string matching; handle no-match exit status; recognize wrapper differences around -H and -r; and switch to tar when the file is a .tar.bz2 archive. Keep bzegrep and bzfgrep as legacy names, not the default for new scripts.

Share this guide

Help another Linux user troubleshoot faster

Share this guide with someone troubleshooting Linux systems or saving it for later.

Follow LinuxCapable

Want more LinuxCapable guides in Google?

Add LinuxCapable as a preferred source so Google can show more of our fresh Linux tutorials in Top Stories and From your sources when relevant.

Add LinuxCapable as a preferred source on Google
Search LinuxCapable

Need another guide?

Search LinuxCapable for package installs, commands, troubleshooting, and follow-up guides related to what you just read.

Found this guide useful?

Support LinuxCapable to keep tutorials free and up to date.

Buy me a coffeeBuy me a coffee
Before commenting, please review our Comments Policy.
Formatting tips for your comment

You can use basic HTML to format your comment. Useful tags currently allowed in published comments:

You type Result
<code>command</code> command
<strong>bold</strong> bold
<em>italic</em> italic
<a href="https://example.com">link</a> link
<blockquote>quote</blockquote> quote block

Got a Question or Feedback?

We read and reply to every comment - let us know how we can help or improve this guide.

Verify before posting: