grep searches text for lines that match a pattern. It is the quickest way to find an error in a log, a setting in a config file, or a function in thousands of source files. This guide covers the options you will actually use, regular expressions, and practical examples for logs, code and security checks.
grep 'text' file prints matching lines. Add -i to ignore case, -r to search a folder, -n for line numbers, -v to exclude matches, -c to count, -l to list file names, -w for whole words and -F for plain text with no regex. Use -E for extended regular expressions (egrep and fgrep are obsolete), -A, -B and -C for context lines, and zgrep for .gz logs. Quote your pattern in single quotes.
1. Basic syntax
grep [OPTIONS] PATTERN [FILE...]grep 'error' app.log # lines containing "error"
grep 'error' app.log old.log # several files; each line is prefixed with its file name
dmesg | grep -i usb # search the output of another commandUse single quotes around the pattern so the shell does not expand $, * or ! before grep sees them. grep is case-sensitive unless you add -i.
grep also reports through its exit status, which is useful in scripts: 0 means a match was found, 1 means none, 2 means an error such as a missing file.
if grep -q 'maintenance_mode=1' config.ini; then
echo 'Site is in maintenance mode'
fi2. The options you will use most
| Option | What it does | Example |
|---|---|---|
-i | Ignore upper and lower case | grep -i 'warning' app.log |
-v | Show lines that do NOT match | grep -v '^#' config.conf |
-n | Show line numbers | grep -n 'DB_HOST' .env |
-c | Count matching lines | grep -c 'POST' access.log |
-l / -L | List files that do / do not match | grep -rl 'wp_mail' wp-content/ |
-w | Match whole words only | grep -w 'id' schema.sql |
-x | Match whole lines only | grep -x 'enabled' flags.txt |
-o | Print only the matching part | grep -o 'user=[a-z]*' app.log |
-m N | Stop after N matches | grep -m 5 'error' big.log |
-F | Treat the pattern as plain text | grep -F '$price[0]' *.php |
-e | Give several patterns | grep -e 'error' -e 'fatal' app.log |
-f FILE | Read patterns from a file, one per line | grep -f bad-ips.txt access.log |
-h / -H | Hide / show file names | grep -h 'error' *.log |
-s | Hide "no such file" and permission errors | grep -rs 'secret' /etc |
Options can be combined: grep -rniw 'todo' src/ searches a folder recursively, ignoring case, for the whole word "todo", with line numbers.
3. Context lines
A single log line rarely tells the whole story. Show what came before and after it:
grep -A 3 'Exception' app.log # 3 lines After each match
grep -B 2 'Exception' app.log # 2 lines Before
grep -C 5 'Exception' app.log # 5 lines of Context on both sidesGroups of lines are separated by --.
4. Regular expressions
By default grep uses basic regular expressions (BRE). With -E you get extended syntax (ERE), where +, ?, |, {} and () work without backslashes. egrep and fgrep are old names for grep -E and grep -F; current GNU grep prints a warning when you use them.
| Pattern | Matches |
|---|---|
^error | Lines starting with "error" |
error$ | Lines ending with "error" |
. | Any single character |
[0-9] | One digit |
[^a-z] | Any character that is not a lower-case letter |
colou?r (with -E) | "color" or "colour" |
[0-9]{3} (with -E) | Exactly three digits |
\bword\b | "word" as a whole word (GNU grep) |
With -E, a vertical bar means "or": grep -E 'cat|dog' matches either word.
grep -E '^(GET|POST) ' requests.txt
grep -Eo '[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}' contacts.txt # pull out email addresses
grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}' access.log | sort -u # unique IPv4 addressesGNU grep also has -P for Perl-compatible expressions, which adds lookarounds and \d:
grep -oP '(?<=order_id=)\d+' app.log # the number after "order_id="To search for text containing regex characters, such as a.b or $var[0], use -F so nothing is treated as a pattern.
5. Searching folders
grep -rn 'DB_PASSWORD' ~/public_html/ # every file under the folder
grep -rn --include='*.php' 'mysql_query' ~/public_html/ # only PHP files
grep -rn --exclude-dir={node_modules,vendor,.git} 'TODO' . # skip heavy folders
grep -rl 'old-domain.com' ~/public_html/ # just the file names-r follows symbolic links only when you name them on the command line; -R follows every link it meets. Hidden files and folders are searched by -r like any others. --include and --exclude-dir make big searches much faster.
To combine grep with other file tests, such as "PHP files changed in the last day", use find:
find ~/public_html -name '*.php' -mtime -1 -exec grep -Hn 'eval(' {} +6. Log files
Compressed and rotated logs need zgrep, which takes the same options:
zgrep -h ' 404 ' access.log.*.gz | wc -lUseful one-liners for a web server access log in the common "combined" format:
# Top 10 IP addresses by number of requests
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head
# Top URLs returning 404 (field 9 is the status, field 7 the path)
awk '$9 == 404 {print $7}' access.log | sort | uniq -c | sort -rn | head
# All requests from one IP in one hour
grep '^203\.0\.113\.7 ' access.log | grep '23/Sep/2026:14:'
# Login attempts on WordPress
grep -c 'POST /wp-login.php' access.logMatching the status code with awk is more accurate than grep ' 404 ', which also matches a response size of 404 bytes.
7. Security checks on a website
grep is a quick first look when you suspect a hacked site. These patterns are common in injected PHP, but legitimate plugins use some of them too, so read each result before deleting anything:
grep -rnE --include='*.php' 'eval\(|base64_decode\(|gzinflate\(|str_rot13\(' ~/public_html/
grep -rn --include='*.php' 'assert(\$_' ~/public_html/
find ~/public_html/wp-content/uploads -name '*.php' # PHP files do not belong in uploadsFor the full clean-up process, see Security checklist: what to do if your website has been hacked.
8. System logs on your own server
On a VPS where you are the administrator, where authentication failures are logged depends on the distribution: /var/log/auth.log on Debian and Ubuntu, /var/log/secure on AlmaLinux and Rocky Linux. Newer Debian releases log to the systemd journal by default instead, so pipe journalctl into grep:
# Failed SSH logins, most frequent IPs first
journalctl -u ssh -u sshd --since today | grep -E 'Failed|Invalid user' \
| grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}' | sort | uniq -c | sort -rn | headTo block repeat offenders automatically, use a tool such as fail2ban or your firewall's own brute-force protection rather than a grep loop.
9. Faster alternatives
For large codebases, ripgrep (rg) is a popular alternative: it searches recursively by default, skips files listed in .gitignore, and is usually faster than grep. git grep searches only the files tracked in a Git repository. Both accept most of grep's options and regex syntax. grep remains the tool that exists on every Linux server.
10. Using grep on Domain India hosting
Jailed SSH access is available on every shared hosting plan (cPanel, DirectAdmin, Webuzo). It is off by default, so ask support to enable it; you then log in with an SSH key, not a password. See Enabling and accessing jailed SSH. Inside the jailed shell, grep searches the files in your own account, such as your website folders. Server-wide system logs are not part of your account.
On a VPS you have full root access and can search every log on the server. VPS hosting is self-managed and comes without a control panel. The card shows the live monthly price, excluding 18% GST.
- 1 vCPU
- 2 GB DDR4 RAM
- 64 GB NVMe SSD Storage
- 2 TB Monthly Bandwidth
How do I search for text in all files in a folder with grep?
Use grep -r followed by the pattern and the folder, for example grep -rn 'text' /path/to/folder. Add --include='*.php' to limit the search to one file type, and -l to print only the names of the matching files.
How do I make grep ignore case?
Add the -i option, for example grep -i 'error' app.log. It then matches error, Error and ERROR.
What is the difference between grep -E and egrep?
They do the same thing: search with extended regular expressions, where +, ?, | and () work without backslashes. egrep is an obsolete name, and current GNU grep prints a warning when it is used, so write grep -E instead.
How do I show lines around a grep match?
Use -A N for N lines after the match, -B N for N lines before, or -C N for N lines on both sides, for example grep -C 3 'Exception' app.log.
How do I search compressed .gz log files?
Use zgrep, which works like grep on gzip-compressed files, for example zgrep 'error' access.log.1.gz. It accepts the same options as grep.
How do I search for text that contains special characters like dots or dollar signs?
Use grep -F, which treats the pattern as plain text instead of a regular expression, and put the pattern in single quotes so the shell does not change it.
Can I use grep on shared hosting?
Yes, once jailed SSH access is enabled on your account; ask Domain India support to switch it on. You can then search the files in your own account. Server-wide system logs are not available on shared hosting.
Ready to start searching? Get jailed SSH enabled on your hosting, or choose a VPS if you need root access to every log on the server.
A self-managed Linux VPS with full root access and your choice of distribution.
See VPS plans