Grep
Complete grep reference with pattern matching, regular expressions, flags, context options, and practical examples for searching text files
No commands found
Try adjusting your search term
Getting Started
Introduction to grep and basic concepts
What is Grep
Understanding grep and its use cases for text searching
Grep overview and basic usage
Grep searches for lines containing the pattern "ap" regardless of position in the line.
# Grep stands for: global regular expression print# It searches for lines matching a pattern in files
# Basic syntax: grep [OPTIONS] PATTERN [FILE...]# Prints lines that match the pattern
# Key features:# - Search multiple files# - Use regular expressions for powerful patterns# - Filter and display specific lines# - Count matches# - Case-insensitive search# - Show context around matchesecho -e "apple\nbanana\ncherry\napricot" | grep "ap"appleapricot- Grep is case-sensitive by default
- Pattern can be literal text or regular expression
- Matches any line containing the pattern (substring match)
- Returns nothing if no matches found
Grep vs other text processing tools
Grep excels at simple pattern matching and filtering. The ^ anchor matches line start, filtering only error lines.
# Compare grep with similar tools:# grep: Search for patterns in lines (filtering)# sed: Stream editor for text transformations# awk: Full text processing language with patterns# find: Search for files by name or properties
# Use grep when you need:# - Quick pattern matching in text# - Filter lines based on conditions# - Search in multiple files# - Use regular expressions for searchecho -e "error: connection failed\ninfo: starting\nerror: timeout" | grep "^error"error: connection failederror: timeout- Grep is best for pattern filtering tasks
- More efficient than awk for simple searches
- Easier than sed for match-based filtering
- Can pipe to other commands for complex workflows
Installation and Setup
Installing grep and verifying functionality
Verify grep installation
Grep is typically pre-installed on Linux and Unix systems. Display version and confirm functionality.
# Check if grep is installedwhich grep
# Display grep versiongrep --version
# Show grep helpgrep --help | head -20grep --versiongrep (GNU grep) 3.7Copyright (C) 2021 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later.- Grep is usually included by default on Linux systems
- Different implementations: GNU grep, BSD grep
- GNU grep typically more feature-rich
- Version may vary across systems
Install grep on different systems
Installation of grep across different Linux distributions and macOS systems.
# Ubuntu/Debiansudo apt-get updatesudo apt-get install -y grep
# CentOS/RHELsudo yum install -y grep
# macOS (BSD grep is default)brew install grep # Installs GNU grep as ggrep
# Alpine Linuxapk add grep
# Arch Linuxsudo pacman -S grepwhich grep && grep --version | head -1/usr/bin/grepgrep (GNU grep) 3.7- GNU grep is most feature-complete version
- macOS comes with BSD grep; install GNU grep with Homebrew
- Always available on standard Linux deployments
- Some advanced flags may not work on BSD grep
Basic Pattern Matching
Simple text search and basic pattern techniques
Simple Text Search
Basic pattern matching for literal text
Search for literal text in files
Grep searches for any line containing the pattern "hello" anywhere in the line.
# Search for a pattern in a filegrep "pattern" filename
# Search in multiple filesgrep "pattern" file1 file2 file3
# Search with different patternsgrep "hello" sample.txtgrep "error" log.txtgrep "TODO" code.pyecho -e "function test() {\n console.log('hello')\n}\ntest('world')" | grep "hello"console.log('hello')- Grep is case-sensitive by default
- Pattern is a substring match (anywhere in line)
- Returns full line containing match, not just the matched text
- Returns nothing if no matches found
Read from standard input
Grep processes standard input when no file is specified, useful in pipelines.
# Pipe command output to grepcat file.txt | grep "pattern"
# Use echo to create inputecho "test string" | grep "test"
# Chain multiple commandscat log.txt | grep "error" | grep "database"echo -e "line1\nerror: failed\nline3\nerror: retry" | grep "error"error: failederror: retry- Use pipe | to send data to grep
- Grep waits for input from stdin if no file given
- Useful in command pipelines for filtering
- Can filter output from other commands
Case-Insensitive Search
Matching patterns regardless of letter case
Case-insensitive search with -i flag
The -i flag makes grep ignore case differences, matching all variations of the pattern.
# Search ignoring case with -i flaggrep -i "pattern" filename
# Works for any case combinationgrep -i "ERROR" file.txt # matches: error, Error, ERRORgrep -i "hello" text.txt # matches: hello, Hello, HELLOecho -e "Hello World\nhello world\nHELLO WORLD" | grep -i "hello"Hello Worldhello worldHELLO WORLD- -i stands for --ignore-case
- Matches regardless of uppercase/lowercase
- Useful for log files with inconsistent capitalization
- Works with literal text and regular expressions
Case-insensitive search in multiple files
Case-insensitive search matches all variations having the pattern.
# Search multiple files ignoring casegrep -i "Warning" *.log
# Combine with line numbersgrep -in "ERROR" error.loggrep -in "info" system.logecho -e "WARNING: disk full\nWarning: memory\nwARNING: cpu" | grep -i "warning"WARNING: disk fullWarning: memorywARNING: cpu- Useful for searching logs with variable capitalization
- Can combine -i with other flags like -n or -c
- Works effectively in pipelines
Whole Word Matching
Match complete words without partial matches
Match whole words with -w flag
The -w flag matches only "cat" as a complete word, excluding "concatenate" which contains "cat" as part of a larger word.
# -w flag matches only complete wordsgrep -w "word" filename
# Avoids partial matches# "word" matches: word, the word is# "word" does NOT match: sword, wording, foreword
grep -w "cat" pets.txt # only standalone "cat"grep -w "test" code.py # only "test" word, not in "testing"echo -e "the cat sat\nconcatenate strings\ncat is here" | grep -w "cat"the cat satcat is here- -w stands for --word-regexp
- Matches word boundaries (space, punctuation, start/end)
- Useful for searching code to avoid partial matches
- Works with regular expressions too
Whole word search ignoring case
Combining -i and -w provides case-insensitive whole word matching.
# Combine -w with -i for case-insensitive word matchinggrep -iw "The" text.txt
# Searches for complete words ignoring casegrep -iw "error" log.txt # matches: error, Error, ERRORgrep -iw "function" code.js # matches complete word "function"echo -e "The quick brown fox\nthe lazy dog\nThey will go" | grep -iw "the"The quick brown foxthe lazy dog- -iw combines ignore-case and word-regexp
- More flexible searching for code and logs
- Avoids false positives from partial matches
Whole Line Matching
Match patterns that span entire lines
Match exact lines with -x flag
The -x flag only matches lines containing exactly "test" with nothing else.
# -x flag matches entire line onlygrep -x "exact line" filename
# Pattern must match complete line (not substring)# "test" matches: test (exact match)# "test" does NOT match: test123, mytest, testing
grep -x "TRUE" config.txtgrep -x "done" status.logecho -e "test\ntest123\nmy test\nonlytest" | grep -x "test"test- -x stands for --line-regexp
- Useful for matching configuration file values
- Equivalent to anchoring pattern with ^...$
- Strict matching without partial line matches
Exact line matching with regex patterns
-x requires the pattern to match the complete line. The pattern matches exactly 3 digits.
# Use -x with regex for exact line patternsgrep -x "status:.*" config.txt
# Match specific line formatgrep -x "[0-9]\{3\}" numbers.txt # exactly 3 digitsgrep -xE "^[a-z]+$" words.txt # lowercase letters onlyecho -e "123\n12\n1234\n12a" | grep -x "[0-9][0-9][0-9]"123- -x requires complete line match including spaces
- Combine with -E for extended regex
- Useful for structured data validation
Multiple Patterns
Search for multiple patterns using different methods
Match multiple patterns with -e flag
The -e flag allows matching multiple patterns. Lines matching any pattern are included.
# Use -e for each pattern (OR logic)grep -e "pattern1" -e "pattern2" filename
# Matches lines with pattern1 OR pattern2grep -e "error" -e "warning" log.txtgrep -e "TODO" -e "FIXME" code.py
# Can use multiple -e flagsgrep -e "info" -e "debug" -e "error" app.logecho -e "error: failed\nwarning: deprecated\ninfo: started\nerror: retry" | grep -e "error" -e "warning"error: failedwarning: deprecatederror: retry- Each -e adds another pattern to match (OR logic)
- Returns lines matching any pattern
- Useful for filtering multiple categories
- Can combine with other flags like -i or -c
Alternation with extended regex
The -E flag enables extended regex with | for alternation, matching any alternative.
# Use pipe | for alternation with -E flaggrep -E "pattern1|pattern2" filename
# Single pattern but with alternativesgrep -E "error|warning" log.txtgrep -E "\.js|\.ts" files.txt
# More complex patternsgrep -E "(fruit|vegetable)" grocery.txtecho -e "apple fruit\nbroccoli vegetable\nstrawberry fruit\ncarrot vegetable" | grep -E "fruit|vegetable"apple fruitbroccoli vegetablestrawberry fruitcarrot vegetable- -E enables extended regular expressions
- Pipe | provides cleaner syntax for multiple patterns
- Works with groups: (pattern1|pattern2)
- More flexible than multiple -e flags
Regular Expressions
Advanced pattern matching using regular expressions
Basic Regular Expressions
Basic regex patterns and syntax
Basic regex metacharacters
The ^ anchor matches only lines starting with "error". The $ would match lines ending with a pattern.
# Basic regex characters (BRE - Basic Regular Expressions)# . = any character# * = zero or more of previous# ^ = start of line# $ = end of line# [abc] = any of a, b, c# [^abc] = not a, b, or c
grep "^error" log.txt # lines starting with errorgrep "\.py$" files.txt # lines ending with .pygrep "^[0-9]" data.txt # lines starting with digitecho -e "error: failed\nwarning: check\nerror: retry\ninfo: started" | grep "^error"error: failederror: retry- Grep uses Basic Regular Expressions (BRE) by default
- In BRE, some characters need backslash escaping
- ^ and $ are line anchors, not in pattern
- . matches any single character except newline
Character classes and ranges
The pattern "test[0-9]" matches "test" followed by any single digit.
# Character classes [] match any character in the setgrep "[0-9]" file.txt # any digitgrep "[a-z]" file.txt # any lowercase lettergrep "[A-Z]" file.txt # any uppercase lettergrep "[a-zA-Z]" file.txt # any lettergrep "[^0-9]" file.txt # NOT a digit
# Common patternsgrep "[aeiou]" words.txt # contains vowelgrep "test[0-9]" results.txt # test followed by digitecho -e "test1\ntest2a\nrandom\ntest" | grep "test[0-9]"test1test2a- [0-9] is equivalent to \d in other regex flavors
- [^...] negates the character class
- Ranges use hyphen: [a-z] for lowercase letters
- Order doesn't matter in character class
Extended Regular Expressions
Enhanced regex syntax with -E flag
Extended regex patterns with -E
The -E flag enables extended regex. The + means one or more, matching test followed by one or more digits.
# Extended Regular Expressions (ERE) with -E flag# + = one or more# ? = zero or one# () = grouping# | = alternation# {} = repetition count
grep -E "error+" log.txt # error, errorr, errorrrgrep -E "test[0-9]+" file.txt # test followed by 1+ digitsgrep -E "colou?r" text.txt # color or colourgrep -E "(cat|dog)" pets.txt # cat or dogecho -e "test\ntest1\ntest123\ntest1a" | grep -E "test[0-9]+"test1test123test1a- -E flag enables extended regex (ERE)
- Cleaner syntax than BRE with + ? {n,m}
- More intuitive than escaping in BRE
- Recommended for complex patterns
Complex extended regex patterns
The pattern validates exact format - three digits, hyphen, two digits, hyphen, four digits, with ^ and $ anchors.
# Complex patterns with extended regexgrep -E "^[0-9]{3}-[0-9]{2}-[0-9]{4}$" ssn.txtgrep -E "^[a-z]+@[a-z]+\.[a-z]+$" emails.txtgrep -E "^https?://" urls.txtgrep -E "^(admin|root):" /etc/passwd
# Combinations with modifiersgrep -E "(test|demo)_[0-9]{2,4}" files.txtecho -e "123-45-6789\n12-45-6789\nabc-45-6789" | grep -E "^[0-9]{3}-[0-9]{2}-[0-9]{4}$"123-45-6789- {n,m} matches between n and m occurrences
- {n} matches exactly n occurrences
- Anchors ^ and $ ensure exact matches
- Parentheses group patterns for | alternation
Anchors and Boundaries
Line and word boundary patterns
Line anchors for position matching
The $ anchor matches "error" only at the end of the line, not in the middle.
# ^ = start of line# $ = end of line
grep "^error" log.txt # lines starting with errorgrep "\.log$" files.txt # lines ending with .loggrep "^$" file.txt # empty linesgrep "^[0-9]" data.txt # lines starting with digitgrep "success$" results.txt # lines ending with successecho -e "error: failed\nwarning: error\nerror at end" | grep "error$"error at end- ^ matches position before first character
- $ matches position after last character
- ^$ together match entirely empty lines
- Anchors match position, not actual content
Word boundaries in extended regex
Word boundaries \b match "test" only as a standalone word, not within "marketesting" or "testing".
# Word boundary matching (requires -E or -P)grep -E "\\btest\\b" file.txt # complete wordgrep -E "^[a-z]+$" words.txt # exactly lowercasegrep -E "\\bserver\\b:" config.txt # word boundary match
# Alternative: use -w flag for word boundariesgrep -w "test" file.txt # simpler approachecho -e "test word\nmarketesting\ntest: started\ntesting" | grep -E "\\btest\\b"test wordtest: started- \b matches word boundaries (letter/non-letter transitions)
- -w flag provides simpler word boundary matching
- Anchors ^ and $ prevent partial matches
Repetition Operators
Matching repeated characters and patterns
Repetition with asterisk and plus
The + operator requires at least one 'u'. With *, zero or more would match "color" too.
# * = zero or more of previous (BRE default)# + = one or more of previous (requires -E)
grep "error*" log.txt # error, eror, errror (BRE)grep -E "error+" log.txt # error, errorr, errror (ERE)grep -E "a+b" file.txt # a, aa, aaa, ... followed by bgrep -E "0*1" file.txt # 1, 01, 001, etc
# Practical examplesgrep "^#+$" readme.txt # lines of only # charactersgrep -E "^-+$" file.txt # separator lines (dashes)echo -e "color\ncolour\ncolouur\ncolr" | grep -E "colou+r"colourcolourr- * includes zero occurrences (matches "error" for pattern "error*")
- + requires at least one (doesn't match "error" for pattern "error+")
- Use -E for + operator
- Without -E, need to escape: \+
Counting repetitions with braces
The {2,4} pattern matches 2 to 4 'a' characters, excluding single 'a' and 'aaaa'.
# {n} = exactly n times# {n,m} = between n and m times# {n,} = n or more times
grep -E "a{2}" file.txt # aa, aaa, aaaagrep -E "a{2,4}" file.txt # aa, aaa, aaaagrep -E "[0-9]{3}" file.txt # exactly 3 digitsgrep -E "[0-9]{2,}" file.txt # 2 or more digits
# Real-world examplesgrep -E "[0-9]{3}-[0-9]{3}-[0-9]{4}" phones.txt # phone regexecho -e "a\naa\naaa\naaaa\naaaaa" | grep -E "a{2,4}"aaaaaaaaa- {n,m} is more precise than * or +
- Useful for validation patterns
- Requires -E flag
- BRE requires escaping: \{n,m\}
Output Control
Controlling what grep displays
Count Matches and Suppress Output
Count matching lines and suppress normal output
Count matching lines with -c
The -c flag returns count of matching lines (3) instead of printing them.
# -c flag counts matching lines instead of printing themgrep -c "pattern" filename
# Shows number of lines matching, not the linesgrep -c "error" log.txt # outputs: 42grep -c "warning" log.txt # outputs: 13grep -c "^#" script.sh # count comment lines
# Combine with other patternsgrep -c "^" file.txt # total line countecho -e "error\nwarning\nerror\nerror\ninfo" | grep -c "error"3- -c counts matching lines, not total matches
- Useful for statistics and reporting
- Returns 0 if no matches found
- Faster than counting lines manually
Suppress output with -q
The -q flag suppresses output and returns exit code to check if pattern exists.
# -q (quiet) suppresses output# Returns exit code: 0 if match found, 1 otherwisegrep -q "pattern" filename
# Useful in scripts for conditional logicif grep -q "error" log.txt; then echo "Errors found"fi
# Check if word exists in filegrep -q "^root:" /etc/passwd && echo "root user exists"echo -e "apple\nbanana\ncherry" | grep -q "banana" && echo "found"found- -q returns exit code (0=found, 1=not found)
- No output produced with -q
- Useful in conditional statements and scripts
- Faster than redirecting to /dev/null
Line Numbers and File Names
Display line numbers and file names in output
Display line numbers with -n
The -n flag shows line numbers (2 and 4) before each matching line.
# -n flag displays line numbers before each matchgrep -n "pattern" filename
# Shows line number and matched linegrep -n "error" log.txtgrep -n "TODO" code.pygrep -n "(function|method)" *.js
# Useful with head/tail for contextgrep -n "pattern" file.txt | head -5echo -e "line1\nerror: failed\nline3\nerror: retry\nline5" | grep -n "error"2:error: failed4:error: retry- Line numbers are 1-based (first line is 1)
- Useful for locating errors in code/logs
- Can navigate directly to line with editor :N syntax
- Combine with pipes for further filtering
Show file names with -H and -h
The -H flag shows filename with each match when searching multiple files.
# -H flag shows filename for each matchgrep -H "pattern" *.txt
# -h flag suppresses filename (default for single file)grep -h "pattern" file1.txt file2.txt
# Combine -H with line numbersgrep -Hn "ERROR" *.log
# Useful with multiple file searchesgrep -r -H "pattern" directory/echo "error message" > /tmp/test1.txt && echo "error found" > /tmp/test2.txt && grep -H "error" /tmp/test*.txt/tmp/test1.txt:error message/tmp/test2.txt:error found- -H shows filename (useful for multiple files)
- -h suppresses filename (useful to avoid duplicates)
- Default behavior varies by grep implementation
- Combine -H and -n: grep -Hn pattern file produces file:line:text
Show Only Matched Text
Display only the matched portion of lines
Show only matched part with -o
The -o flag shows only matched patterns, not full lines.
# -o flag shows only the matched text, not full linesgrep -o "pattern" filename
# Useful for extracting specific patternsgrep -o "[0-9]*\.[0-9]*" file.txt # numbers with decimalsgrep -o "[a-z]*@[a-z]*" emails.txt # email addressesgrep -oE "https?://[^ ]+" urls.txt # URLs
# Count matches (not lines) with -o and -cgrep -o "word" file.txt | wc -lecho "error: 123 warning: 456 error: 789" | grep -o "error: [0-9]*"error: 123error: 789- -o shows only matched text, not full line
- Useful for extracting data (numbers, emails, URLs)
- Can pipe to other commands for further processing
- One match per line in output
Extract patterns with -o and regex
The -o flag with -E extracts phone numbers matching the pattern.
# Extract specific data from structured textgrep -oE "[0-9]{3}-[0-9]{3}-[0-9]{4}" data.txt # phone numbersgrep -oE "[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}" file.txt # emailsgrep -oE "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}" log.txt # IPs
# Count specific matchesgrep -o "abc" myfile.txt | wc -l # count "abc" occurrencesecho "Call: 555-123-4567 or 555-987-6543" | grep -oE "[0-9]{3}-[0-9]{3}-[0-9]{4}"555-123-4567555-987-6543- Perfect for data extraction from text
- Combine with pipes for processing: grep -o "pattern" | sort | uniq
- Works well with extended regex (-E)
Color Output and Byte Offsets
Highlight matches and show byte positions
Color output with highlight
The --color flag highlights matching text, useful for visual inspection.
# --color flag highlights matches with colorgrep --color "pattern" filename
# Force color output (useful in pipes)grep --color=always "error" log.txt | less -R
# Disable color outputgrep --color=never "pattern" file.txt
# Color in pipelines (useful for inspection)cat log.txt | grep --color=always "error"echo "error in line\nno match here\nerror again" | grep --color=always "error"error in lineerror again- --color highlights the matched portion
- Default is automatic color detection
- Use --color=always in pipes to force coloring
- Use --color=never to suppress coloring
Show byte offset with -b
The -b flag shows byte offset (10) where "def" begins in that line.
# -b flag shows byte offset of matchesgrep -b "pattern" filename
# Shows position from start of line where match beginsgrep -b "error" log.txtgrep -bn "pattern" file.txt # with line numbers
# Useful for binary file analysisgrep -b "signature" binary_file | headecho -e "123456789\nabcdefghij\n0123456789" | grep -b "def"10:abcdefghij- -b shows byte position from start of line
- Useful for binary files and precise positioning
- Can combine with -n for line and byte info
- Less common flag but useful for specialized tasks
Context and Line Selection
Display context around matches and filter lines
Context Lines Around Matches
Show lines before and after matches
Show context with -B, -A, and -C
The -A 2 flag shows the matching line plus 2 lines after it.
# -B NUM = lines before match# -A NUM = lines after match# -C NUM = lines before and after match
grep -B 2 "error" log.txt # 2 lines beforegrep -A 3 "ERROR" log.txt # 3 lines aftergrep -C 1 "pattern" file.txt # 1 line before and after
# Useful for understanding contextgrep -B 5 -A 5 "Search term" document.txtgrep -C 2 "Connection refused" system.logecho -e "start\nline2\nerror\nline4\nline5" | grep -A 2 "error"errorline4line5- -A adds lines after the match
- -B adds lines before the match
- -C adds both before and after
- NUM is the number of lines to display
Context with line numbers and colors
Multiple context groups are separated by dashes. Each match shows surrounding lines.
# Combine context with other useful flagsgrep -C 3 -n "pattern" file.txt # context + line numbersgrep -C 2 --color "error" log.txt # context + color
# Separate output with dashes (useful for multiple groups)grep --color=always -C 2 "error" large.log | less -R
# Multiple occurrences show with separatorsgrep -B 1 -A 1 "pattern" file.txtecho -e "line1\nline2\nerror message\nline4\nline5\nerror again\nline7" | grep -B 1 -A 1 "error"line2error messageline4--line5error againline7- Dashes (--) separate different match groups
- Very useful for understanding error context in logs
- Combine with -n for precise line location
- Better than scrolling through large files
Invert Match
Show lines NOT matching the pattern
Exclude pattern with -v
The -v flag inverts match, showing only lines NOT starting with 'a'.
# -v flag shows lines NOT matching patterngrep -v "pattern" filename
# Useful for filtering out unwanted linesgrep -v "^#" config.txt # exclude commentsgrep -v "^$" file.txt # exclude empty linesgrep -v "debug" app.log # exclude debug logsgrep -v "exclude_this" data.txt # exclude specific textecho -e "apple\nbanana\napricot\norange" | grep -v "^a"orange- -v negates the pattern (shows non-matching lines)
- Useful for filtering out unwanted content
- Works with any pattern or regex
- Returns all non-matching lines
Multiple inverted patterns
Multiple -v flags exclude both "debug" and "info" lines, leaving only "error" lines.
# Stack multiple -v flags to exclude multiple patternsgrep -v 'debug' -v 'info' log.txt
# Exclude multiple patternsgrep -v '^#' -v '^$' config.txt # no comments, no blank lines
# Combined with other flagsgrep -vn "error" app.log # exclude errors with line numbersgrep -vic "pattern" file.txt # case-insensitive invert + countecho -e "debug: test\ninfo: started\nerror: failed\ninfo: complete" | grep -v "^debug" | grep -v "^info"error: failed- Multiple -v flags provide AND logic (exclude all patterns)
- Different from -e patterns which are OR logic
- Useful for multi-stage filtering
Max Count and File Listing
Limit matches and show files with matches
Limit matches with -m
The -m 2 flag stops after finding 2 matches.
# -m NUM flag stops after NUM matchesgrep -m 5 "pattern" filename
# Shows only first N matching linesgrep -m 1 "error" log.txt # first error onlygrep -m 10 "warning" app.log # first 10 warnings
# Useful for large files to get quick previewgrep -m 5 "todo" project.txt # first 5 TODOsecho -e "error1\nerror2\nerror3\nerror4\nerror5" | grep -m 2 "error"error1error2- -m NUM sets maximum number of matches to display
- Grep stops reading file after NUM matches
- Useful for performance on large files
- Faster than showing all matches and piping to head
List files with matches
The -l flag shows only filenames containing the pattern, not the matching lines.
# -l flag lists only filenames (one per line) with matchesgrep -l "pattern" *.txt
# -L flag lists only filenames WITHOUT matchesgrep -L "pattern" *.txt
# Useful for finding which files contain/lack contentgrep -r -l "TODO" src/ # files with TODO commentsgrep -r -L "license" docs/ # files without license headerecho "test" > /tmp/file1.txt && echo "other" > /tmp/file2.txt && grep -l "test" /tmp/file*.txt/tmp/file1.txt- -l lists filenames only (helpful for further processing)
- -L lists filenames that DON'T match
- Useful with xargs: grep -l "pattern" * | xargs cmd
- Very fast since grep stops after first match
File and Directory Operations
Search across files and directories
Recursive Directory Search
Search patterns across multiple files and directories
Recursive search with -r
The -r flag searches recursively through all subdirectories.
# -r flag searches directories recursivelygrep -r "pattern" directory/
# Searches all files in directory and subdirectoriesgrep -r "TODO" src/ # find TODOs in codegrep -r "error" logs/ # search all log filesgrep -r "function test" project/ # search all files
# Show filenames with resultsgrep -r -H "pattern" directory/grep -rn "pattern" src/ # with line numbersmkdir -p /tmp/search_test/sub && echo "test line" > /tmp/search_test/file1.txt && echo "test data" > /tmp/search_test/sub/file2.txt && grep -r "test" /tmp/search_test/tmp/search_test/file1.txt:test line/tmp/search_test/sub/file2.txt:test data- -r searches directories recursively
- Includes all files in subdirectories
- Shows filename by default with -r
- Useful for code search across projects
Follow symlinks with -R
The -R flag follows symlinks, so both real and linked paths are searched.
# -R flag follows symbolic links (vs -r which doesn't)grep -R "pattern" directory/
# Searches through symlinked directoriesgrep -R "config" /grep -Rn "pattern" src/
# Difference from -r# -r: skip symlinks# -R: follow symlinks (like -r --dereference)
# Exclude patterns for more controlgrep -R --exclude="*.log" "pattern" src/mkdir -p /tmp/test_symlink/real && echo "found" > /tmp/test_symlink/real/file.txt && ln -s real /tmp/test_symlink/link && grep -R "found" /tmp/test_symlink/tmp/test_symlink/real/file.txt:found/tmp/test_symlink/link/file.txt:found- -R follows symbolic links (-r does not)
- Important for complex directory structures
- Can cause infinite loops with circular symlinks
- Use --exclude-dir to skip problematic directories
File and Directory Exclusion
Skip specific files and directories from search
Exclude files by pattern
The --exclude flag skips .log files, showing only the match in file.txt.
# --exclude filters specific file patternsgrep -r --exclude="*.log" "pattern" directory/
# Exclude multiple patternsgrep -r --exclude="*.log" --exclude="*.tmp" "pattern" src/
# Exclude directories to speed up searchgrep -r --exclude-dir="node_modules" "pattern" project/grep -r --exclude-dir=".git" --exclude-dir="*.log" "pattern" .
# Common exclusionsgrep -r --exclude-dir=target --exclude-dir=build "pattern" project/mkdir -p /tmp/excl_test && echo "search" > /tmp/excl_test/file.txt && echo "skip" > /tmp/excl_test/file.log && grep -r --exclude="*.log" "search\|skip" /tmp/excl_test/tmp/excl_test/file.txt:search- --exclude patterns skip specific file types
- --exclude-dir skips entire directories
- Multiple exclusions require separate flags
- Greatly speeds up searches in large projects
Include only specific files
The --include flag searches only .py files, skipping the .java file.
# --include filters to specific file patternsgrep -r --include="*.py" "pattern" src/
# Search only specific file typesgrep -r --include="*.js" --include="*.ts" "import" src/
# Combine include and excludegrep -r --include="*.log" --exclude="debug.log" "error" logs/
# More flexible than just excludinggrep -r --include="[Mm]akefile*" "target" .mkdir -p /tmp/incl_test && echo "python" > /tmp/incl_test/script.py && echo "java" > /tmp/incl_test/Main.java && grep -r --include="*.py" "python\|java" /tmp/incl_test/tmp/incl_test/script.py:python- --include specifies which files to search
- More precise control than --exclude
- Multiple includes require separate flags
- Useful for language-specific searches
Binary Files and Special Input
Handle binary files and null-separated input
Handle binary files
The -a flag treats input as text even if it contains binary data.
# --binary-files specifies how to handle binarygrep --binary-files=text "pattern" binaryfile
# -a flag treats binary as text (like --binary-files=text)grep -a "pattern" binaryfile
# Useful with binary files that contain textgrep -a "version" compiled_binary
# Skip binary files entirelygrep -r --binary-files=without-match "pattern" .echo "Hello binary world" | grep -a "world"Hello binary world- Grep skips binary files by default
- -a treats binary input as text characters
- Useful for searching in compiled binaries
- May produce garbage output with true binary
Null-separated input and output
The -z flag treats null bytes as line separators instead of newlines.
# -z flag handles null-separated input/outputgrep -z "pattern" null_separated_file
# Useful with find -print0 for safe handlingfind . -name "*.txt" -print0 | xargs -0 grep "pattern"
# Process filenames with spaces safelyfind . -type f -print0 | xargs -0 grep -z "pattern"
# Combine with other flagsgrep -rz "pattern" directory/printf "line1\0line2\0line3" | grep -z "line2"line2- -z handles null-delimited input
- Important for xargs and find with -print0
- Allows searching paths with special characters
- Necessary for robust script handling
Practical Examples and Advanced Usage
Real-world scenarios and complex grep patterns
Real-World Use Cases
Practical examples of grep in common scenarios
Search and analyze log files
Extract specific error types from log entries using piped grep commands.
# Count errors in log filegrep -c "ERROR" app.log
# Show recent errors with contextgrep -n -A 2 "ERROR" app.log | tail -20
# Extract specific informationgrep "timestamp:" server.log | grep -o "[0-9:-]*"
# Find patterns across multiple logsgrep -r "Connection refused" var/log/ | sort | uniq
# Get error summarygrep "ERROR" app.log | grep -o "code: [0-9]*" | sort | uniq -cecho -e "2025-02-28 ERROR: db connection\n2025-02-28 ERROR: timeout\n2025-02-28 INFO: OK" | grep "ERROR" | grep -o "ERROR: [a-z]*"ERROR: dbERROR: timeout- Combine grep commands for complex analysis
- Use grep -o to extract specific data
- Pipe to sort and uniq for summaries
- Great for log analysis and debugging
Search source code
Find TODO comments in source code with line numbers for quick navigation.
# Find function definitionsgrep -rn "^function " src/
# Find TODO and FIXME commentsgrep -r "TODO\|FIXME" src/ --include="*.js"
# Find unused importsgrep -r "^import" src/ | grep -v "from"
# Find break points (in debugging)grep -rn "debugger;" src/
# Search class definitionsgrep -rn "^class " src/ --include="*.js"mkdir -p /tmp/src && echo -e "function test() {}\n// TODO: fix this\nfunction main() {}" > /tmp/src/app.js && grep -n "TODO" /tmp/src/app.js2:// TODO: fix this- Combine patterns for specific code elements
- Use line numbers for quick editor navigation
- Useful for code review and cleanup
Advanced Regular Expression Patterns
Complex regex patterns for specialized searches
Complex validation patterns
Validates email format using extended regex with character classes and anchors.
# Email validation (basic)grep -E "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$" emails.txt
# IP address validationgrep -E "^([0-9]{1,3}\.){3}[0-9]{1,3}$" ips.txt
# URL validationgrep -oE "https?://[^ ]+" urls.txt
# Phone number validationgrep -E "^\+?[1-9]\d{1,14}$" phones.txt
# Hexadecimal color codesgrep -oE "#[0-9a-fA-F]{6}" colors.txtecho -e "user@example.com\ninvalid.email\ntest@domain.co.uk" | grep -E "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"user@example.comtest@domain.co.uk- Regex validation is pattern-based, not perfect
- Works well for basic format checking
- Can be combined with other tools for perfect validation
- Test patterns carefully before deployment
Negative lookahead and grep
Use pipes to negate patterns that grep doesn't support with lookahead.
# Grep doesn't support lookahead, use alternatives# Find lines WITHOUT a pattern (use -v)grep -v "exclude_this" file.txt
# Find lines with pattern but NOT followed by anothergrep "error" file.txt | grep -v "error: handled"
# Complex exclusions with multiple patternsgrep -v "debug\|test\|verbose" app.log
# Lines with pattern A but not pattern Bgrep "function" code.js | grep -v "function test"echo -e "error: critical\nerror: handled\nerror: warning\nerror: critical" | grep "error" | grep -v "error: handled"error: criticalerror: warningerror: critical- Grep doesn't support lookahead/lookbehind assertions
- Use pipes with -v to achieve similar results
- Multiple -v flags work with AND logic
- Efficient approach for most use cases
Performance Optimization
Tips for efficient grep usage on large files
Optimize grep performance
Fixed string search (-F) is fastest for literal patterns, useful for large files.
# Use fixed string search instead of regex (fastest)grep -F "literal text" large_file.txt
# Use -m to limit results on large filesgrep -m 100 "pattern" huge.log
# Use -l to find files first, then grep specific onesfind . -name "*.log" | xargs grep "pattern"
# Exclude heavy directories earlygrep -r --exclude-dir=node_modules --exclude-dir=.git "pattern" .
# Use word boundaries to eliminate false positivesgrep -w "word" file.txt # avoids partial matchesseq 1 10000 | python3 -c "import sys; print('\n'.join(['test' + str(i) for i in range(10000)]))" | grep -F "test5000"test5000- -F (fixed string) is much faster than regex
- -m limits results for quick previews
- Exclude unnecessary directories with --exclude-dir
- Use find | xargs for complex file selection
Parallel grep for distributed search
Parallel processing with xargs can speed up searching multiple files.
# Use parallel grep on multiple filesfind . -type f -name "*.log" | parallel grep "pattern"
# Or use xargs with multiple jobsfind . -type f | xargs -P 4 grep "pattern"
# Split large file and search partssplit -l 100000 huge.log part_grep "pattern" part_* &
# GNU parallel syntaxls *.log | parallel grep "pattern" {}echo -e "test1\ntest2\ntest3" | xargs -P 2 grep "test"test1test2test3- xargs -P specifies number of parallel processes
- Most beneficial with hundreds of files
- GNU parallel is more flexible than xargs
- Check available CPU before setting job count