How to Search Text in Files Linux: grep Examples

Search text in files in Linux with grep — recursive search, regex patterns, context lines, count matches, and real-world log investigation examples.

April 22, 2026·5 min read·Damon

grep is the tool you use more than almost anything else on Linux. Search a file, search a directory, match patterns, count occurrences, extract specific fields.


TL;DR

grep "error" /var/log/app.log              # basic search
grep -r "error" /var/log/                 # recursive search
grep -i "error" /var/log/app.log          # case-insensitive
grep -n "error" /var/log/app.log          # show line numbers
grep -c "error" /var/log/app.log          # count matches
grep -v "debug" /var/log/app.log          # exclude matches

Basic grep

# Search in a file
grep "connection refused" /var/log/nginx/error.log

# Case-insensitive
grep -i "error" /var/log/app.log

# Show line numbers
grep -n "FATAL" /var/log/app.log

# Count matching lines
grep -c "ERROR" /var/log/app.log

# Invert (show lines NOT matching)
grep -v "DEBUG" /var/log/app.log | head -20

Recursive Search

# Search all files in a directory
grep -r "password" /etc/

# With filename shown (default for -r)
grep -r "api_key" /opt/app/

# Only show filenames that contain the match
grep -rl "DatabaseError" /opt/app/

# Exclude certain file types
grep -r --include="*.py" "import requests" /opt/app/
grep -r --exclude="*.log" "error" /var/
grep -r --exclude-dir=".git" "TODO" /opt/app/

Context Lines

# 3 lines before and after each match
grep -B3 -A3 "FATAL" /var/log/app.log

# 5 lines after (useful for stack traces)
grep -A5 "Exception" /var/log/app.log

# 2 lines before (useful for request context before error)
grep -B2 "500 Internal Server Error" /var/log/nginx/access.log

Multiple Patterns

# Match either pattern (OR)
grep -E "ERROR|FATAL|CRITICAL" /var/log/app.log

# Match both patterns (AND) — pipe two greps
grep "ERROR" /var/log/app.log | grep "database"

# Multiple patterns from file
grep -f /tmp/patterns.txt /var/log/app.log

Extended Regex (-E)

# Match ERROR or WARN
grep -E "ERROR|WARN" /var/log/app.log

# Match lines starting with a timestamp
grep -E "^[0-9]{4}-[0-9]{2}-[0-9]{2}" /var/log/app.log

# Match IP addresses
grep -E "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}" /var/log/nginx/access.log

# Match HTTP 5xx errors in nginx access log
grep -E '" [5][0-9]{2} ' /var/log/nginx/access.log

Real Examples

Find all errors in log files from today

# Assuming log format starts with date
grep "$(date +%Y-%m-%d)" /var/log/app.log | grep -i "error\|fatal"

Find failed SSH logins

grep "Failed password" /var/log/auth.log

# With count per IP
grep "Failed password" /var/log/auth.log \
  | grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' \
  | sort | uniq -c | sort -rn | head -10

Search nginx access log for slow responses

# Last field is response time if configured
grep " 200 " /var/log/nginx/access.log | awk '$NF > 2.0' | wc -l
# Count responses over 2 seconds

Find which config file has a specific setting

grep -r "worker_processes" /etc/nginx/
# /etc/nginx/nginx.conf:worker_processes auto;

Search compressed log files

# zgrep works on .gz files without decompressing
zgrep "ERROR" /var/log/app/app.log.gz

# Search current + all rotated logs
grep "ERROR" /var/log/app.log*
zgrep "ERROR" /var/log/app.log.*.gz

Output Formatting

# Only show matching part (not whole line)
grep -o "ERROR.*" /var/log/app.log | head -10

# Highlight matches (color)
grep --color=always "ERROR" /var/log/app.log | less -R

# With filename prefix (default for multi-file search)
grep "error" /var/log/*.log

# Without filename prefix (for single file piped output)
grep -h "error" /var/log/app.log

# Show only filename
grep -l "critical" /var/log/*.log

Common Mistakes

Mistake 1: Not quoting patterns with spaces or special chars

grep "connection refused" file.log    # CORRECT — quoted
grep connection refused file.log       # WRONG — "refused" is treated as filename

Mistake 2: Slow recursive search on /var/log grep -r "pattern" / reads every file. Limit the scope:

grep -r "error" /var/log/app/    # specific directory
grep -r --include="*.log" "error" /var/log/    # specific extension

Mistake 3: Using grep to count unique values

grep -c "error" file    # counts LINES with "error", not unique errors
grep "error" file | sort | uniq -c    # count per unique error message

Mistake 4: Forgetting -E for extended regex grep "error|fatal" looks for literal "error|fatal". Use grep -E "error|fatal" for OR.


Quick Reference

grep "pattern" file              # basic search
grep -i "pattern" file           # case-insensitive
grep -r "pattern" dir/           # recursive
grep -n "pattern" file           # line numbers
grep -c "pattern" file           # count
grep -v "pattern" file           # invert (exclude)
grep -l "pattern" files          # only filenames
grep -A3 "pattern" file          # 3 lines after
grep -B3 "pattern" file          # 3 lines before
grep -E "pat1|pat2" file         # OR pattern
grep -rn --include="*.py" "func" # recursive, specific extension
zgrep "pattern" file.gz          # search compressed file

Conclusion

grep with -r for directories, -i for case-insensitive, -n for line numbers, -E for regex with |. Combine with sort | uniq -c | sort -rn to count and rank unique patterns. For log analysis specifically, pipe chains like grep "ERROR" | grep "database" | wc -l answer specific questions quickly.


Related: Linux Log Analysis: Debug Issues Like a Senior Engineer — grep in the context of full log investigation. How to Monitor Real-Time Logs Linux — combining grep with tail -f.