ripgrep (rg) β Fast Recursive Search#
Installation#
# Debian/Ubuntu
sudo apt install ripgrep
# Fedora/RHEL
sudo dnf install ripgrep
# macOS
brew install ripgrep
# cargo
cargo install ripgrep
Basic usage#
rg pattern # search cwd recursively
rg pattern file.txt # search a single file
rg pattern src/ tests/ # search specific directories
rg -e pattern1 -e pattern2 # multiple patterns (OR)
Common flags#
| Flag | Meaning |
|---|
-i | Case-insensitive |
-v | Invert match |
-n | Line numbers (on by default) |
-l | Filenames only |
-c | Count per file |
-w | Whole word |
-x | Whole line |
-o | Only matching part |
-A N | N lines after |
-B N | N lines before |
-C N | N lines context |
-m N | Max N matches |
-q | Quiet (exit code only) |
--no-filename / -I | Suppress filenames |
File filtering#
rg pattern -g "*.py" # glob: only .py files
rg pattern -g "!*.min.js" # glob: exclude minified
rg pattern -g "src/**/*.ts" # glob: nested path
rg pattern -t py # by type alias
rg pattern -t-py # exclude a type
rg --type-list # list all known type aliases
rg pattern --hidden # include hidden files (.dotfiles)
rg pattern --no-ignore # ignore .gitignore
rg pattern --no-ignore-vcs # ignore only VCS ignores
rg pattern -u # unrestricted (= --no-ignore)
rg pattern -uu # + include hidden files
rg pattern -uuu # + search binary files
Regex (Rust regex by default)#
rg '\b\d{4}-\d{2}-\d{2}\b' # date pattern
rg '(?i)error' # inline case-insensitive flag
rg '^import\s' --type ts # TS import lines
# PCRE2 (lookahead, lookbehind, backreferences)
rg -P '(?<=href=")[^"]*' # PCRE2 lookbehind
rg -P '\w+(?=\.log)' # lookahead
Fixed strings#
rg -F 'function(x, y)' # treat pattern as literal string
rg -F '$.prototype' # special chars safe
rg pattern --no-heading # flat output, one match per line
rg pattern --heading # group by file (default)
rg pattern --json # machine-readable JSON
rg pattern --color never # disable colour
rg pattern --column # show column number
rg pattern --line-number # redundant (on by default), explicit
rg pattern --pretty # force colour + headings in pipe
Replace (display only β does not modify files)#
rg pattern -r replacement # show lines with substitution applied
rg 'foo(\w+)' -r 'bar$1' # with capture group
Searching compressed files#
rg -z pattern file.gz # decompress on the fly
rg -z pattern logs/ # recursively in .gz/.xz/.bz2
Config file ~/.config/ripgrep/ripgreprc#
# Ignore node_modules globally
--glob=!node_modules
# Default type filters
--type-add=web:*.{html,css,js,ts,tsx}
# Always show line numbers
--line-number
# Use PCRE2 by default
--engine=pcre2
# Point to a custom config
RIPGREP_CONFIG_PATH=~/.ripgreprc rg pattern
Practical examples#
# Find all TODO/FIXME comments in a codebase
rg '(TODO|FIXME|HACK|XXX)' --type py --type ts
# Search for a function definition
rg 'def\s+authenticate' -t py
# Find files importing a specific module
rg '^import.*from.*lodash' -t ts -l
# Extract all email addresses
rg -oP '[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}' --no-filename | sort -u
# Find duplicate lines within a file
rg '^(.+)$' file.txt --no-filename | sort | uniq -d
# Count lines matching pattern across all .log files
rg -c 'ERROR' -g "*.log" | awk -F: '{s+=$2} END {print s}'
# Live search a growing log file
tail -f /var/log/syslog | rg --passthru 'error|warn'
# Replace preview (what sed -i would change)
rg 'oldname' -r 'newname' --passthru src/
rg vs grep equivalents#
| grep | rg |
|---|
grep -r pattern . | rg pattern |
grep -rn pattern . | rg pattern (numbers default) |
grep -rl pattern . | rg -l pattern |
grep -ri pattern . | rg -i pattern |
grep --include="*.py" | rg -t py or rg -g "*.py" |
grep -rP pattern . | rg -P pattern |
[!TIP]
rg --files lists every file rg would search (respecting ignores) without actually searching. Useful for debugging why a file is included or excluded.