Search & Regex
Find files by name, search text inside files, and use regex patterns — the core skill for navigating any codebase from the terminal.
Recipe
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.
Working Example
# "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 -rnfor recursive search with line numbersrg(ripgrep) is significantly faster and auto-ignores.gitignorepatterns-lflag shows only filenames, useful for piping to other commandsfindcombined with-not -pathto exclude directories
Deep Dive
find — Locate Files by Name, Type, Size, Date
# 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 filenamesgrep — Search Text Inside Files
# 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/ripgrep (rg) — Modern grep Replacement
# 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 filesRegex Patterns — Quick Reference
# 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 parenthesisPractical Regex Examples for Codebases
# 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/sed — Find and Replace in Files
# 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.tsxawk — Extract and Transform Text
# 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 -rnGotchas
Things 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: Userg(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
sedrequires-i ''(empty string for backup extension), Linux doesn't. Fix: Usesed -i '' 's/.../.../' fileon macOS or install GNU sed:brew install gnu-sed. -
Regex metacharacters in search strings — Searching for literal
[,.,(etc. without escaping. Fix: Usegrep -Forrg -Ffor fixed (non-regex) strings. -
Missing results with basic grep regex — Some patterns like
\d,+,\wneed extended regex. Fix: Usegrep -E(extended) orgrep -P(Perl-compatible) for advanced patterns.
Alternatives
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 |
FAQs
What is the difference between grep and rg (ripgrep)?
rgis significantly faster, especially on large codebasesrgauto-ignores files listed in.gitignoregrepis pre-installed everywhere;rgmay need to be installed separately
How do I search for a literal string that contains regex special characters?
grep -F "array.map((item) =>" src/
# or
rg -F "array.map((item) =>" src/- The
-Fflag treats the pattern as a fixed string, not a regex
How do I find all files modified in the last hour?
find . -name "*.tsx" -mmin -60-mmin -60means modified less than 60 minutes ago-mtime -1means modified in the last 24 hours
How do I exclude node_modules from my searches?
- With
grep:grep -rn "pattern" --exclude-dir=node_modules . - With
find:find . -name "*.ts" -not -path "*/node_modules/*" - With
rg: automatic (respects.gitignore)
What is the difference between grep -E and grep -P?
-Eenables extended regex (supports+,?,|,()without escaping)-Penables Perl-compatible regex (supports\d,\w,\b, lookaheads)- Use
-Efor most cases; use-Pwhen you need advanced patterns
Gotcha: Why does sed -i behave differently on macOS vs Linux?
- macOS
sedrequires an empty string for in-place editing:sed -i '' 's/old/new/g' file - Linux
seddoes not:sed -i 's/old/new/g' file - Install GNU sed on macOS with
brew install gnu-sedfor consistent behavior
How do I find all React component definitions in a codebase?
rg "export (default )?(function|const) [A-Z]\w+" -t tsx- This matches both function declarations and arrow function components
How do I do a find-and-replace across multiple files?
find src -name "*.tsx" -exec sed -i '' 's/OldName/NewName/g' {} \;- Always preview first with
sed 's/OldName/NewName/g' file.tsx(no-i)
Gotcha: My grep regex with \d is not matching digits. Why?
- Basic
grepdoes not support\d; use[0-9]instead - Or use extended/Perl regex:
grep -P "\d+" fileorgrep -E "[0-9]+" file
How do I count the number of matches per file?
grep -rc "import" src/ | sort -t: -k2 -rn | head -10-cprints a count per file instead of matching lines
How do I find empty catch blocks in TypeScript files?
rg -U "catch\s*\([^)]*\)\s*\{\s*\}" src/-Uenables multiline matching- Empty catch blocks silently swallow errors and should be avoided
How can I search for TypeScript type definitions across the project?
rg "^(export )?(type|interface) \w+" -t ts- Matches both
typeandinterfacedeclarations - Add
-lto list only the file paths
Related
- Sysadmin Essentials — Process, disk, network, and service management
- Node.js Developer Commands — npm, environment, and build commands
- Shell Productivity — Pipes, redirection, scripting, and workflow tips