The grep command in Linux
grep searches text for lines matching a pattern and prints them. It is arguably the most useful text tool on any Unix system: you will use it to dig through logs, filter the output of other commands, and locate where something is defined in a codebase. The name comes from the old editor command g/re/p — "globally search a regular expression and print".
How grep works
grep streams input line by line, testing each against a compiled pattern and printing the survivors. The pattern is compiled once into a matching automaton before any data is read — the reason grep chews through gigabytes at hundreds of MB/s.
Its three dialects are really three engines. Basic regex (default) and extended regex (-E) differ mainly in which characters are special; -F disables regex entirely and uses fast literal-string search — the right choice when hunting for text full of dots and brackets. Two more internals worth knowing: locale affects both speed and matching (LC_ALL=C makes grep dramatically faster on ASCII logs), and a file containing NUL bytes flips grep into "binary file matches" mode unless you force -a.
Syntax
grep [OPTIONS] PATTERN [FILE...] Common options
| Option | What it does |
|---|---|
-i | Ignore case: "Error", "ERROR" and "error" all match. |
-v | Invert: print lines that do NOT match. |
-n | Prefix each matching line with its line number. |
-r | Recursive: search every file under a directory. |
-l | Print only the names of files that contain a match. |
-c | Print only the count of matching lines. |
-w | Match whole words only: "log" will not match "login". |
-A n / -B n / -C n | Show n lines of context After, Before, or around (Center) each match. |
-E | Extended regular expressions (alternation with |, + and ? without escaping). |
How to use grep: examples
$ grep error app.log Print every line of app.log containing "error".
$ grep -i error app.log Same, but case-insensitive — catches Error and ERROR too.
$ grep -rn "TODO" src/ Search recursively through a directory, showing file names and line numbers. The classic way to find every TODO in a project.
$ grep -v "^#" config.conf Show a config file without its comment lines: -v inverts, and ^# matches lines starting with #.
$ ps aux | grep nginx Filter the output of another command through a pipe — one of the most common grep patterns.
$ grep -c "GET" access.log Count how many lines contain GET, without printing them.
$ grep -E "warn|error" app.log Extended regex: match lines containing either word.
$ grep -B 2 -A 5 "Exception" app.log Print each match with 2 lines before and 5 after — invaluable for reading stack traces in logs.
Real-world use cases for grep
Incident triage in logs
Production alarm at 3am: grep -i error /var/log/app/*.log finds the failures; add -B2 -A5 for context around each, and -c to gauge the scale. This sequence — match, context, count — is the universal first response to any log-based incident.
Auditing a codebase
Where is that setting used? grep -rn "MAX_RETRIES" src/ answers in milliseconds with file and line numbers. Before IDE indexing, and still today over SSH, recursive grep is how engineers navigate unfamiliar code.
Try grep yourself
This is a live sandbox with a small filesystem (documents/, notes.txt,
backup.sh…). Nothing you do here can break anything — experiment freely.
Try: grep -i bash notes.txt
Pro tips and common mistakes
- grep -rn pattern dir/ (recursive + line numbers) is the form to memorize — it covers 80% of real usage.
- Filtering ps output? pgrep name replaces ps aux | grep name and doesn't match itself.
- Speed on big trees: grep excludes nothing by default; --include="*.py" or ripgrep (rg) skip binaries and node_modules and are dramatically faster.
- grep -F treats the pattern as a literal string, not a regex — essential when searching for text containing dots, brackets or dollar signs.
- Combine with -l to get just filenames, then feed them onward: grep -rl "old-domain.com" . | xargs sed -i "s/old-domain/new-domain/g".
Frequently asked questions about grep
How do I grep recursively through directories?
Use grep -r pattern directory/. Adding -n includes line numbers: grep -rn "TODO" src/ is the standard form.
How do I search for lines that do NOT contain a word?
Invert the match with -v: grep -v debug app.log prints every line that does not contain "debug".
What is the difference between grep, egrep and fgrep?
egrep is equivalent to grep -E (extended regex) and fgrep to grep -F (fixed strings, no regex). The standalone names are deprecated; use the flags instead.
Can grep search multiple patterns at once?
Yes: grep -E "one|two" file, or repeat -e: grep -e one -e two file.
Related commands
Print file contents, number lines, and join multiple files together.
findLocate files anywhere in a directory tree by name, type, size, date — and act on them.