grep: search text for patterns
grep prints every line that matches a pattern. It searches files, whole directory trees or the output of other commands, and it is probably the single most useful Unix tool.
Common options
| Option | Meaning |
|---|---|
-i | Ignore case |
-w | Match whole words only |
-v | Show lines that do not match |
-n | Show line numbers |
-c | Count matching lines |
-l / -L | List files that match / do not match |
-r, -R | Search directories recursively (-R follows links) |
-A n, -B n, -C n | Show n lines after, before, or around each match |
-E | Extended regular expressions (|, +, ?, {} without backslashes) |
-F | Fixed string: no regular expression at all |
-P | Perl-compatible regular expressions (GNU) |
-o | Print only the matching part |
-q | Quiet: just set the exit status (for scripts) |
Search files
grep "Failed password" /var/log/auth.log
grep -i error app.log # Error, ERROR, error …
grep -n "listen" /etc/nginx/nginx.conf # with line numbers
grep -w root /etc/passwd # the word root, not "chroot"
grep -c "GET /" access.log # how many lines
grep -v "^#" sshd_config | grep -v "^$" # config without comments and blank lines
Search directories
grep -rn "DB_PASSWORD" /var/www/app # recursive, with file names and line numbers
grep -rl "old.example.com" /etc # just the file names
grep -r --include="*.php" "eval(" . # only PHP files (GNU, BSD)
grep -r --exclude-dir=node_modules "TODO" src/
On systems whose grep has no -r (older AIX, Solaris and HP-UX), combine find and grep: find . -type f -exec grep -l "pattern" {} +.
Context around matches
grep -C 3 "OutOfMemoryError" app.log # 3 lines before and after
grep -A 10 "Traceback" app.log # the 10 lines after each traceback
Regular expressions
| Pattern | Matches |
|---|---|
^abc / abc$ | Lines starting / ending with abc |
. | Any one character |
a* | Zero or more a |
[0-9], [^0-9] | A digit, anything but a digit |
a+, a?, a{3} | One or more, zero or one, exactly three (with -E) |
cat|dog | Either word (with -E) |
\bword\b | Word boundaries (GNU, or use -w) |
grep -E "error|warning|critical" syslog
grep -E "^[0-9]{1,3}(\.[0-9]{1,3}){3}$" ips.txt # lines that look like IPv4 addresses
grep -oE "[[:alnum:]._%+-]+@[[:alnum:].-]+\.[a-z]{2,}" file # extract e-mail addresses
grep -P "\d{4}-\d{2}-\d{2}" log # Perl syntax: \d for digits
grep -F "a.b*c" file # search the literal text a.b*c
Quote patterns in single quotes when they contain $, * or backslashes, so the shell does not change them.
In scripts
if grep -q "^allow_root=yes" /etc/app.conf; then
echo "root access is enabled" >&2
fi
grep exits with 0 if it found a match, 1 if not, and 2 on an error.
Faster alternatives
For searching large source trees, ripgrep (rg) is much faster and skips files listed in .gitignore automatically. egrep and fgrep are obsolete names for grep -E and grep -F; upstream GNU grep 3.8 and later warns when you use them (Debian and Ubuntu remove the warning). Use grep -E and grep -F in scripts.