grep or ripgrep
grep is on every Unix machine and handles one file at a time. ripgrep (rg)
is built for a source tree: it walks directories in parallel, skips what
.gitignore skips, and uses a regex engine that cannot go exponential. Both
match lines against a pattern; the differences that matter are in what they
search by default and how fast they get through a tree.
What differs
- Concurrency
rgwalks the tree and searches files on all cores at once, each thread with its own matcher.grep -ris one thread, in order. On a large repo the performance difference is substantial, more on fast storage. On one file, or on a pipe, they are close.- Ignore files
rgreads.gitignore,.ignoreand.rgignore, skips hidden files and does not follow symlinks;--no-ignore,--hiddenand-Lturn each back on.grepsearches everything unless told--exclude-dirby hand.- Binary files
rgstops at the first NUL byte and says so;grepsearches on and prints "binary file matches".-amakes either treat the file as text;rg --binarysearches binaries without printing their lines.- File types
rg -t go,rg -t js -t ts,rg -T minified: a built-in table of extensions, wheregrepneeds--include='*.go'or afind.- Regex syntax
grepdefaults to basic syntax, where+,?,|and groups need a backslash;-Egives the extended one and-PPerl's.rgis extended by default, with\bfor word boundaries and lazy quantifiers, and-Pfor look-around and backreferences, which its own engine leaves out to stay linear.- Portability
grepis POSIX and present on anything with a shell; a script that must run anywhere uses it.rgis a package to install, so it belongs to user editor, terminal, ..., not in/etc/cron.d.
Usage patterns
rg pattern # the tree, in parallel, ignore files honoured
rg -t go -w Lookup # whole word, Go files only
rg -F 'a.literal[string]' # no regex
rg -uu pattern # hidden and ignored files too (-uuu: binaries as well)
grep -rn pattern dir # the same tree, one thread, nothing skipped
grep -E 'a|b' file # extended syntax; plain grep needs 'a\|b'
Both read a pipe the same way, so journalctl -f | grep x and
journalctl -f | rg x are interchangeable; grep starts a few
milliseconds faster, which matters only in a loop.