Skip to content

Grep - Text Search

Grep is a powerful tool for searching text patterns in files. This guide covers how to use grep (and its equivalents) across PowerShell, Mac, and Linux.

Search Text Inside a File

Linux/Mac

bash
# Basic search (case-sensitive)
grep "pattern" file.txt

# Case-insensitive search (recommended)
grep -i "pattern" file.txt

# Show line numbers
grep -n -i "pattern" file.txt

# Show lines before and after match
grep -C 3 -i "pattern" file.txt  # 3 lines before and after
grep -B 2 -i "pattern" file.txt  # 2 lines before
grep -A 2 -i "pattern" file.txt  # 2 lines after

# Count matches
grep -c -i "pattern" file.txt

# Show only matching part
grep -o -i "pattern" file.txt

# Invert match (lines that don't match)
grep -v -i "pattern" file.txt

# Multiple patterns
grep -i -e "pattern1" -e "pattern2" file.txt

PowerShell

powershell
# Basic search (case-insensitive by default)
Select-String -Path "file.txt" -Pattern "pattern"

# Case-sensitive search
Select-String -Path "file.txt" -Pattern "pattern" -CaseSensitive

# Show line numbers (included by default)
Select-String -Path "file.txt" -Pattern "pattern"

# Show context lines
Select-String -Path "file.txt" -Pattern "pattern" -Context 2,3  # 2 before, 3 after

# Count matches
(Select-String -Path "file.txt" -Pattern "pattern").Count

# Multiple patterns
Select-String -Path "file.txt" -Pattern "pattern1|pattern2"

# Get only the matching text
Select-String -Path "file.txt" -Pattern "pattern" | ForEach-Object { $_.Matches.Value }

Find Files Containing Text

Linux/Mac

bash
# Search in current directory
grep -i "pattern" *

# Search recursively in all files
grep -r -i "pattern" .

# Search recursively with line numbers
grep -r -n -i "pattern" .

# Search only specific file types
grep -r -i "pattern" --include="*.txt" .
grep -r -i "pattern" --include="*.js" --include="*.ts" .

# Exclude directories
grep -r -i "pattern" --exclude-dir=node_modules --exclude-dir=.git .

# Show only filenames (no matches)
grep -r -l -i "pattern" .

# Search with word boundaries
grep -r -w -i "pattern" .

# Count matches per file
grep -r -c -i "pattern" . | grep -v ":0$"

# Complex example: search in JavaScript files, exclude node_modules
grep -r -n -i "function.*user" --include="*.js" --exclude-dir=node_modules .

Mac (Additional Options)

bash
# Using grep with find for better control
find . -type f -name "*.txt" -exec grep -i "pattern" {} +

# Search with mdfind (Spotlight)
mdfind "kMDItemTextContent == '*pattern*'c"

# Using ripgrep (faster alternative, install via: brew install ripgrep)
rg -i "pattern"
rg -i "pattern" -g "*.js"  # Only .js files

PowerShell

powershell
# Search in current directory
Get-ChildItem -Filter *.txt | Select-String -Pattern "pattern"

# Search recursively
Get-ChildItem -Recurse -Filter *.txt | Select-String -Pattern "pattern"

# Search all files recursively (no filter)
Get-ChildItem -Recurse -File | Select-String -Pattern "pattern"

# Search specific file types
Get-ChildItem -Recurse -Include *.js,*.ts | Select-String -Pattern "pattern"

# Exclude directories
Get-ChildItem -Recurse -File | Where-Object { $_.FullName -notmatch "node_modules|\.git" } | Select-String -Pattern "pattern"

# Show only unique filenames
Get-ChildItem -Recurse -File | Select-String -Pattern "pattern" | Select-Object -Unique Path

# Show filename and line number
Get-ChildItem -Recurse -Include *.txt | Select-String -Pattern "pattern" | Select-Object Path, LineNumber, Line

# Count matches per file
Get-ChildItem -Recurse -Include *.txt | ForEach-Object {
    $matches = (Select-String -Path $_.FullName -Pattern "pattern" -AllMatches).Matches.Count
    if ($matches -gt 0) {
        [PSCustomObject]@{
            File = $_.Name
            Matches = $matches
        }
    }
}

# Complex example: search "function" in JavaScript files, exclude node_modules
Get-ChildItem -Recurse -Include *.js |
    Where-Object { $_.FullName -notmatch "node_modules" } |
    Select-String -Pattern "function.*user"

Regular Expressions

Common Patterns

bash
# Email addresses
grep -E -i "[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}" file.txt

# IP addresses
grep -E "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}" file.txt

# URLs
grep -E -i "https?://[^\s]+" file.txt

# Phone numbers (US format)
grep -E "\(?[0-9]{3}\)?[-. ]?[0-9]{3}[-. ]?[0-9]{4}" file.txt

# Dates (YYYY-MM-DD)
grep -E "[0-9]{4}-[0-9]{2}-[0-9]{2}" file.txt

Linux/Mac Regex Options

bash
# Basic regex (default)
grep "pattern" file.txt

# Extended regex
grep -E "pattern1|pattern2" file.txt

# Perl-compatible regex
grep -P "(?<=foo)bar" file.txt  # Lookbehind

# Match whole words
grep -w "word" file.txt

# Match at start of line
grep "^pattern" file.txt

# Match at end of line
grep "pattern$" file.txt

PowerShell Regex

powershell
# Basic regex
Select-String -Path "file.txt" -Pattern "pattern"

# Multiple patterns (OR)
Select-String -Path "file.txt" -Pattern "pattern1|pattern2"

# Word boundaries
Select-String -Path "file.txt" -Pattern "\bword\b"

# Start of line
Select-String -Path "file.txt" -Pattern "^pattern"

# End of line
Select-String -Path "file.txt" -Pattern "pattern$"

# Extract specific groups
Select-String -Path "file.txt" -Pattern "(\d{4})-(\d{2})-(\d{2})" |
    ForEach-Object { $_.Matches.Groups[1..3].Value }

Practical Examples

Find TODO Comments in Code

Linux/Mac:

bash
grep -r -n -i "TODO\|FIXME\|HACK" --include="*.js" --include="*.ts" --exclude-dir=node_modules .

PowerShell:

powershell
Get-ChildItem -Recurse -Include *.js,*.ts |
    Where-Object { $_.FullName -notmatch "node_modules" } |
    Select-String -Pattern "TODO|FIXME|HACK"

Find API Keys or Secrets

Linux/Mac:

bash
grep -r -n -i "api[_-]?key\|secret\|password" --include="*.js" --include="*.env" --exclude-dir=node_modules .

PowerShell:

powershell
Get-ChildItem -Recurse -Include *.js,*.env |
    Where-Object { $_.FullName -notmatch "node_modules" } |
    Select-String -Pattern "api[_-]?key|secret|password"

Find Import Statements

Linux/Mac:

bash
grep -r -n "^import.*from" --include="*.js" --include="*.ts" --exclude-dir=node_modules .

PowerShell:

powershell
Get-ChildItem -Recurse -Include *.js,*.ts |
    Where-Object { $_.FullName -notmatch "node_modules" } |
    Select-String -Pattern "^import.*from"

Find Function Definitions

Linux/Mac:

bash
grep -r -n "function\s\+\w\+" --include="*.js" --exclude-dir=node_modules .

PowerShell:

powershell
Get-ChildItem -Recurse -Include *.js |
    Where-Object { $_.FullName -notmatch "node_modules" } |
    Select-String -Pattern "function\s+\w+"

Search in Log Files

Linux/Mac:

bash
# Find errors in logs
grep -i "error\|exception\|fatal" /var/log/app.log

# Find errors with context
grep -C 5 -i "error" /var/log/app.log

# Find errors in last hour
find /var/log -name "*.log" -mmin -60 -exec grep -i "error" {} +

PowerShell:

powershell
# Find errors in logs
Select-String -Path "C:\logs\app.log" -Pattern "error|exception|fatal"

# Find errors with context
Select-String -Path "C:\logs\app.log" -Pattern "error" -Context 2,3

# Find errors in recent files
Get-ChildItem -Path "C:\logs" -Filter *.log |
    Where-Object { $_.LastWriteTime -gt (Get-Date).AddHours(-1) } |
    Select-String -Pattern "error"

Performance Tips

Linux/Mac

bash
# Use ripgrep (much faster than grep)
brew install ripgrep  # Mac
sudo apt install ripgrep  # Ubuntu/Debian

rg -i "pattern"  # Automatically ignores .git, node_modules, etc.
rg -i "pattern" -g "*.js"  # Only .js files

# Use ag (The Silver Searcher)
brew install the_silver_searcher  # Mac
sudo apt install silversearcher-ag  # Ubuntu/Debian

ag -i "pattern"

PowerShell

powershell
# Use -Include with specific extensions instead of searching all files
Get-ChildItem -Recurse -Include *.txt,*.log | Select-String -Pattern "pattern"

# Use -Filter when possible (faster than -Include for single patterns)
Get-ChildItem -Recurse -Filter *.txt | Select-String -Pattern "pattern"

# Limit depth for faster searches
Get-ChildItem -Recurse -Depth 2 -Include *.txt | Select-String -Pattern "pattern"

Common Options Comparison

FeatureLinux/Mac grepPowerShell Select-String
Case-insensitive-iDefault (use -CaseSensitive to disable)
Recursive search-r or -RGet-ChildItem -Recurse
Show line numbers-nIncluded by default
Count matches-c(Select-String ...).Count
Invert match-v-NotMatch
Show filenames only-lSelect-Object -Unique Path
Context lines-C num-Context num,num
Multiple patterns-e pattern1 -e pattern2-Pattern "pattern1|pattern2"
Exclude directories--exclude-dir=dirWhere-Object { $_.FullName -notmatch "dir" }
File type filter--include="*.ext"-Include *.ext

Aliases and Shortcuts

Linux/Mac

bash
# Add to ~/.bashrc or ~/.zshrc

# Quick recursive grep
alias gr='grep -r -n -i'

# Grep in code files
alias grc='grep -r -n -i --include="*.js" --include="*.ts" --include="*.py" --exclude-dir=node_modules --exclude-dir=.git'

# Find TODO comments
alias todo='grep -r -n "TODO\|FIXME\|HACK" --exclude-dir=node_modules --exclude-dir=.git .'

PowerShell

powershell
# Add to $PROFILE

# Quick search function
function Find-Text {
    param($Pattern, $Path = ".")
    Get-ChildItem -Path $Path -Recurse -File | Select-String -Pattern $Pattern
}
Set-Alias ft Find-Text

# Search in code files
function Find-InCode {
    param($Pattern)
    Get-ChildItem -Recurse -Include *.js,*.ts,*.py |
        Where-Object { $_.FullName -notmatch "node_modules|\.git" } |
        Select-String -Pattern $Pattern
}
Set-Alias fic Find-InCode

See Also

External Resources

Released under the MIT License.