grep: search text for patterns

Updated November 2026

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.

grep [options] pattern [file ...] command | grep [options] pattern

Common options

OptionMeaning
-iIgnore case
-wMatch whole words only
-vShow lines that do not match
-nShow line numbers
-cCount matching lines
-l / -LList files that match / do not match
-r, -RSearch directories recursively (-R follows links)
-A n, -B n, -C nShow n lines after, before, or around each match
-EExtended regular expressions (|, +, ?, {} without backslashes)
-FFixed string: no regular expression at all
-PPerl-compatible regular expressions (GNU)
-oPrint only the matching part
-qQuiet: 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

PatternMatches
^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|dogEither word (with -E)
\bword\bWord 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.