Where to start First steps track · 15 stages
Linux Labs

grep — searching text

4 min GNU grep

The grep command finds lines matching a pattern in files and command output: regex, recursion, context.

Cheat sheet

7 commands Printable version
  • grep -i word file case-insensitive
  • grep -rn word dir/ recursive + line numbers
  • grep -v word file lines without the word
  • grep -C2 word file ±2 lines of context
  • grep -rn --include='*.conf' word /etc
  • grep -oP 'regex' file match only, Perl regex
  • cmd | grep -F "literal" a literal string

Overview

grep finds lines matching a pattern (a regular expression, see regex). It works on files and on stdin (in a pipeline).

bash
grep "error" app.log              # lines containing "error"
journalctl -u nginx | grep 502    # a filter in a pipeline
grep -r "TODO" src/               # recursively through a directory

Options

17
Flag Meaning
-i case-insensitive
-r / -R recursive through directories (R also follows symlinks)
-n show line numbers
-v invert (lines WITHOUT the pattern)
-c count matches
-l / -L only filenames with a match / without one
-w / -x a whole word / a whole line
-E / -F / -P extended regex / a fixed string / Perl regex
-A N/-B N/-C N N lines after / before / around
-o only the matched part
--include/--exclude filter filenames with -r
Option What it does Example
-i --ignore-case Search case-insensitively. grep -i word file
-r --recursive Search directories recursively (-R also follows symlinks). grep -rn word dir/
-n --line-number Show line numbers before matches. grep -n word file
-v --invert-match Show lines that do NOT match the pattern. grep -v word file
-c --count Count matching lines instead of printing them. grep -c "GET" access.log
-l --files-with-matches Show only filenames that contain a match (-L for ones that don't). grep -rl "api_key" .
-w --word-regexp Match the pattern as a whole word. grep -w word file
-E --extended-regexp Extended regular expressions (no need to escape +, ?, |, ()). grep -E "warn|error|fatal" app.log
-F --fixed-strings Search for a literal string, without regex interpretation. grep -F "1.2.3.4" file
-P --perl-regexp Perl-style regex (\d, \w, lookahead, etc.). grep -oP '\d+' file
-A N Show N lines after each match. grep -A3 "panic" app.log
-B N Show N lines before each match. grep -B1 "panic" app.log
-C N Show N lines of context around each match. grep -C2 word file
-o --only-matching Print only the matched part of the line, not the whole line. grep -oP 'regex' file
-x --line-regexp The match must span the entire line. grep -x "exact line" file
--include glob With -r, search only files matching a glob. grep -rn --include='*.conf' word /etc
--exclude-dir glob With -r, skip directories matching a glob. grep -rn --exclude-dir={.git,node_modules} "TODO" .

Nothing found. Try a shorter query.

Recipes

1

Examples

bash
grep -rni "timeout" /etc                    # recursive, case-insensitive, with line numbers
grep -E "warn|error|fatal" app.log          # an alternative (OR)
grep -A3 -B1 "panic" app.log                # context around it
grep -c "GET" access.log                     # how many GET requests
grep -rl "api_key" .                         # which files contain it
grep -rn --include='*.py' "def main" .       # only .py files
grep -rn --exclude-dir={.git,node_modules} "TODO" .
grep -oP '\d+\.\d+\.\d+\.\d+' access.log | sort | uniq -c | sort -rn   # top IPs (-P, -o)
grep -Ff patterns.txt data.txt               # match any line from patterns.txt
ps aux | grep -v grep | grep nginx

Troubleshooting

5

grep itself shows up in ps aux | grep

A classic. Exclude yourself: grep -v grep, or pgrep, or the grep "[n]ginx" trick.

Special characters in the pattern get treated as regex

A dot, brackets, + are regex. Escape them, or use grep -F (a fixed string): grep -F "1.2.3.4".

\d, \w, lookahead don't work

Basic/extended grep doesn't know them — you need -P (PCRE): grep -P '\d{3}'.

I expect matches, but grep is silent

Check the case (-i), the right file, and that the data is actually arriving. grep may skip binary files — -a treats them as text.

Too slow over a large tree

Exclude directories (--exclude-dir), or use ripgrep (rg) — noticeably faster.

See also

  • find — Finding files by name, size, time, permissions; acting on what's found.
  • sed-awk — Stream editing (sed) and column-based processing (awk).
  • files-basics — Navigation and files — ls, cd, cp, mv, rm, cat, less, head, tail, terminal copy-paste.
Loading…