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.
How grep compares
sed edits lines; awk understands columns. Substitution is sed, computation is awk.
grep vs ripgrep (rg)grep is everywhere; ripgrep is dramatically faster on code and respects .gitignore by default.
Things people do with grep
Replace text in one file or across a whole project, safely.
Search text inside filesFind which files contain a word, and exactly where.
Search recursively with grepSearch every file under a directory with grep, show filenames and line numbers, and skip noisy folders.
Search with grep ignoring caseMake grep match Error, ERROR and error with one option.
Search for multiple patterns with grepMatch several words with grep using -e or extended regular expressions.
Find files by name in LinuxLocate files and directories by exact name or wildcard pattern with find.
Search Bash command historyFind a command you ran before using history, reverse search and grep.
Count lines in a Linux fileCount lines, words and bytes with wc, with useful variations for logs and source files.
View the end of a fileUse tail to inspect recent log entries and control how many lines you see.
Watch a Linux log file in real timeFollow new log entries with tail and handle log rotation correctly.
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.