grep
is the fastest way to filter lines that match a pattern across files, directories, or streams. This guide focuses on GNU grep with production-ready examples.
grep PATTERN file
-i
-n
-c
-l
(inverse -L
)-o
-E
-F
-v
-r
(no symlinks), -R
(follow symlinks)-B N
, -A N
, -C N
--include
, --exclude
, --exclude-dir
--color=auto
(force with --color=always
)-I
-Z
(use with xargs -0
)# Recursive search with file filters
grep -Rni --include='*.log' --exclude-dir='.git' 'ERROR' .
# Count matches per file (quick signal for CI)
grep -Rc --include='*.py' 'TODO' src/
# Show only the matched portion (e.g., HTTP status in journal)
journalctl -u nginx | grep -oE 'status=[0-9]{3}'
# Word boundary search (avoid over-matching)
grep -rw --include='*.c' '\<init\>' src/
# Literal text (fast, ignores regex metacharacters)
grep -F '[INFO]' app.log
# Safe with odd filenames (spaces/newlines)
find . -name '*.md' -print0 | xargs -0 grep -n 'architecture'
-F
for literal patterns (often much faster).Use LC_ALL=C
for byte-wise matching and speed on huge inputs:
LC_ALL=C grep -rF 'needle' /data/terabytes
-I
or --binary-files=without-match
.-m N
when you only need the first N hits.--line-buffered
; GNU grep
auto-flushes on line end, but overall pipeline buffering still applies.-E
(ERE): foo|bar
, a{2,5}
, colou?r
, (ba|be)z
.-P
(PCRE) for lookarounds:
grep -Po '(?<=user=)[^ &]+' access.log
Note:
-P
may be missing on stock BSD/macOS grep. Use GNU grep (e.g., Homebrewggrep
) or rewrite withawk
/sed
.
# Show surrounding lines (2 before/after)
grep -nC2 'panic' kernel.log
# Only filenames that contain matches
grep -Rl 'TODO' src/
# Suppress filenames (multi-file, lines only)
grep -h 'pattern' file1 file2
# 1) Summarize error bursts with context around each match
grep -Rni --include='*.log' 'CRITICAL' logs/ | sed -n 's/:.*//p' | sort -u \
| xargs -I{} sh -c "echo '--- {} ---'; grep -nC2 'CRITICAL' {}"
# 2) Extract JSON values (simple cases)
grep -Po '"user_id"\s*:\s*"\K[^"]+' events.jsonl | sort | uniq -c | sort -nr | head
# 3) Find lines NOT matching (e.g., exclude health checks)
grep -R 'GET /' access.log | grep -v '/healthz'
GNU vs BSD (macOS) differences:
-P
often unavailable on BSD grep.man grep
.-F
.LC_ALL=C
.--include/--exclude
and prefer -F
.cat
→ grep pattern file
(pipe only when needed).