Search & Regex
Find files by name, search text inside files, and use regex patterns - the core skill for navigating any codebase from the terminal.
Search across all documentation pages
Find files by name, search text inside files, and use regex patterns - the core skill for navigating any codebase from the terminal.
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥
Quick-reference recipe card - copy-paste ready.
# Find files by name
find . -name "*.tsx" -type f
find . -name "page.tsx" -path "*/app/*"
# Search text inside files
grep -r "useState" src/
grep -rn "TODO" --include="*.ts" .
# Faster alternative (ripgrep)
rg "useState" src/
rg "TODO" -t ts
# Find and replace across files
sed -i '' 's/oldFunction/newFunction/g' src/**/*.tsWhen to reach for this: When you need to find a file, locate where a function is used, search for a pattern across the codebase, or do bulk find-and-replace.
# "Where is this component defined?"
rg "export.*function Header" --include="*.tsx"
# or
grep -rn "export.*function Header" --include="*.tsx" src/
# "Which files import this module?"
rg "from.*@/components/Button" -l
# -l = files only, no matching lines
# "Find all TODO comments with context"
rg "TODO|FIXME|HACK" -t ts -t tsx -C 2
# -C 2 = show 2 lines of context above and below
# "Find large files in the project"
find . -type f -size +1M -not -path "./node_modules/*" -not -path "./.next/*"What this demonstrates:
grep -rn for recursive search with line numbersrg (ripgrep) is significantly faster and auto-ignores .gitignore patterns-l flag shows only filenames, useful for piping to other commandsfind combined with -not -path to exclude directories# Basic name search (case-sensitive)
find . -name "layout.tsx"
# Case-insensitive
find . -iname "readme*"
# By file type
find . -type f # files only
find . -type d # directories only
# By extension pattern
find . -name "*.test.ts"
find . -name "*.md" -o -name "*.mdx" # OR
# Exclude directories
find . -name "*.ts" -not -path "*/node_modules/*" -not -path "*/.next/*"
# By modification time
find . -name "*.tsx" -mtime -1 # modified in last 24 hours
find . -name "*.tsx" -mmin -60 # modified in last 60 minutes
find . -name "*.tsx" -newer reference.txt # newer than a file
# By size
find . -type f -size +500k # larger than 500KB
find . -type f -size -1k # smaller than 1KB
find . -type f -empty # empty files
# Execute a command on results
find . -name "*.test.ts" -exec wc -l {} \;
find . -name "*.log" -exec rm {} \;
find . -name "*.tsx" -exec grep -l "useState" {} \;
# Using xargs (often faster for many files)
find . -name "*.ts" | xargs grep "deprecated"
find . -name "*.tmp" -print0 | xargs -0 rm # handle spaces in filenames# Basic recursive search
grep -r "pattern" directory/
# With line numbers
grep -rn "useState" src/
# Case insensitive
grep -rni "error" src/
# Only filenames (no matching lines)
grep -rl "useEffect" src/components/
# Invert match (lines NOT matching)
grep -v "node_modules" file.txt
# Count matches per file
grep -rc "import" src/ | sort -t: -k2 -rn | head -10
# Filter by file extension
grep -rn "fetchData" --include="*.ts" --include="*.tsx" .
grep -rn "TODO" --include="*.{ts,tsx}" .
# Exclude directories
grep -rn "console.log" --exclude-dir=node_modules --exclude-dir=.next .
# Show context around matches
grep -rn "error" -A 3 src/ # 3 lines After
grep -rn "error" -B 2 src/ # 2 lines Before
grep -rn "error" -C 2 src/ # 2 lines Context (both)
# Match whole words only
grep -rw "use" src/ # matches "use" but not "useState"
# Multiple patterns
grep -rn -e "useState" -e "useEffect" src/# Install
# macOS: brew install ripgrep
# Ubuntu: sudo apt install ripgrep
# Basic search (auto-ignores .gitignore patterns)
rg "pattern" src/
# Filter by file type
rg "useState" -t tsx
rg "TODO" -t ts -t tsx
# Only filenames
rg "useEffect" -l
# Files NOT matching
rg "useEffect" --files-without-match -t tsx
# Fixed string (no regex interpretation)
rg -F "array.map((item) =>" src/
# Multiline search
rg -U "export default function.*\n.*return" src/
# Replace (preview - does not modify files)
rg "oldName" -r "newName"
# Show stats
rg "TODO" --stats
# Search hidden files too
rg "SECRET" --hidden
# Glob patterns
rg "fetch" -g "*.ts" -g "!*.test.ts" # ts files but not test files# Anchors
^start # line starts with "start"
end$ # line ends with "end"
^exact$ # entire line is "exact"
# Character classes
[abc] # a, b, or c
[a-z] # lowercase letter
[0-9] # digit
[^abc] # NOT a, b, or c
. # any single character
# Quantifiers
a* # zero or more a's
a+ # one or more a's
a? # zero or one a
a{3} # exactly 3 a's
a{2,5} # 2 to 5 a's
# Groups and alternation
(foo|bar) # foo or bar
(abc)+ # one or more "abc" sequences
# Common shortcuts
\d # digit [0-9] (extended regex)
\w # word char [a-zA-Z0-9_]
\s # whitespace
\b # word boundary
# Escape special characters
\. # literal dot
\( # literal parenthesis# Find React component definitions
rg "export (default )?(function|const) [A-Z]\w+"
# Find all hook calls
rg "use[A-Z]\w+\(" -t tsx
# Find console.log statements (but not console.error/warn)
rg "console\.log\(" src/
# Find TODO with author
rg "TODO\([^)]+\):" src/
# Find hardcoded URLs
rg "https?://[^\s\"')\]>]+" src/
# Find empty catch blocks
rg -U "catch\s*\([^)]*\)\s*\{\s*\}" src/
# Find imports from a specific package
rg "from ['\"]react['\"]" src/
# Find CSS color hex codes
rg "#[0-9a-fA-F]{3,8}\b" src/
# Find potential API keys (basic pattern)
rg "['\"][A-Za-z0-9_]{20,}['\"]" --include="*.ts" src/
# Find duplicate adjacent words (typos)
rg "\b(\w+)\s+\1\b" docs/# Replace in a single file (macOS - '' is required)
sed -i '' 's/oldText/newText/g' file.tsx
# Replace in a single file (Linux)
sed -i 's/oldText/newText/g' file.tsx
# Preview without modifying (works on both)
sed 's/oldText/newText/g' file.tsx
# Replace across multiple files
find src -name "*.tsx" -exec sed -i '' 's/OldComponent/NewComponent/g' {} \;
# Replace with regex
sed -i '' 's/className="text-[a-z]*"/className="text-base"/g' file.tsx
# Delete lines matching a pattern
sed -i '' '/console\.log/d' src/app/page.tsx
# Replace only on lines matching a condition
sed -i '' '/import/s/react/react-dom/' file.tsx# Print specific columns
ps aux | awk '{print $1, $2, $11}' # user, PID, command
# Sum a column
wc -l src/**/*.tsx | awk '{sum += $1} END {print sum " total lines"}'
# Filter by condition
df -h | awk '$5 > "80%"' # disks over 80% full
# Print lines between patterns
awk '/START/,/END/' file.txt
# Count unique values
git log --format="%an" | sort | uniq -c | sort -rnThings that will bite you. Each gotcha includes what goes wrong, why it happens, and the fix.
grep searches node_modules - Without --exclude-dir, grep searches everything and takes forever. Fix: Use rg (auto-respects .gitignore) or add --exclude-dir=node_modules.
find returns too many results - Searching from / or without excluding directories. Fix: Always scope your search: find src/ ... and use -not -path.
sed differences between macOS and Linux - macOS sed requires -i '' (empty string for backup extension), Linux doesn't. Fix: Use sed -i '' 's/.../.../' file on macOS or install GNU sed: brew install gnu-sed.
Regex metacharacters in search strings - Searching for literal [, ., ( etc. without escaping. Fix: Use grep -F or rg -F for fixed (non-regex) strings.
Missing results with basic grep regex - Some patterns like \d, +, \w need extended regex. Fix: Use grep -E (extended) or grep -P (Perl-compatible) for advanced patterns.
Other ways to solve the same problem - and when each is the better choice.
| Alternative | Use When | Don't Use When |
|---|---|---|
rg (ripgrep) | Fast codebase search, respects .gitignore | Not installed on the server |
ag (silver searcher) | Similar to rg, already installed | rg is available (rg is generally faster) |
fd | Modern find replacement with simpler syntax | Scripting that needs POSIX find compatibility |
| IDE search (Cmd+Shift+F) | Visual context, quick navigation to results | Scripting, automation, or remote servers |
fzf | Interactive fuzzy finding of files and content | Exact pattern matching needed |
rg is significantly faster, especially on large codebasesrg auto-ignores files listed in .gitignoregrep is pre-installed everywhere; rg may need to be installed separatelygrep -F "array.map((item) =>" src/
# or
rg -F "array.map((item) =>" src/-F flag treats the pattern as a fixed string, not a regexfind . -name "*.tsx" -mmin -60-mmin -60 means modified less than 60 minutes ago-mtime -1 means modified in the last 24 hoursgrep: grep -rn "pattern" --exclude-dir=node_modules .find: find . -name "*.ts" -not -path "*/node_modules/*"rg: automatic (respects .gitignore)-E enables extended regex (supports +, ?, |, () without escaping)-P enables Perl-compatible regex (supports \d, \w, \b, lookaheads)-E for most cases; use -P when you need advanced patternssed requires an empty string for in-place editing: sed -i '' 's/old/new/g' filesed does not: sed -i 's/old/new/g' filebrew install gnu-sed for consistent behaviorrg "export (default )?(function|const) [A-Z]\w+" -t tsxfind src -name "*.tsx" -exec sed -i '' 's/OldName/NewName/g' {} \;sed 's/OldName/NewName/g' file.tsx (no -i)grep does not support \d; use [0-9] insteadgrep -P "\d+" file or grep -E "[0-9]+" filegrep -rc "import" src/ | sort -t: -k2 -rn | head -10-c prints a count per file instead of matching linesrg -U "catch\s*\([^)]*\)\s*\{\s*\}" src/-U enables multiline matchingrg "^(export )?(type|interface) \w+" -t tstype and interface declarations-l to list only the file pathsReviewed by Chris St. John·Last updated Jul 10, 2026
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥