Finding things fast: grep, find, ripgrep and fd

Fast search starts with choosing the right question. Use grep and ripgrep when you are searching file contents. Use find and fd when you are searching paths, file names or file me…

Fast search starts with choosing the right question. Use grep and ripgrep when you are searching file contents. Use find and fd when you are searching paths, file names or file metadata. Get that split right and most search problems become easy.

Use grep for dependable text matching

grep prints lines that match a pattern. It is installed almost everywhere, which makes it a good default for scripts and portable documentation.

grep 'listen' nginx.conf
grep -R 'TODO' src

Use -n for line numbers and -i for case-insensitive matching.

grep -Rni 'deprecated' src

Use -F when the pattern is fixed text, not a regular expression. This avoids regex interpretation for characters such as . or [.

grep -RF 'user.name' config

Use -- before paths or patterns that may begin with a hyphen, so they are not mistaken for options.

grep -- '-Xmx' jvm.options

Use find for precise file selection

find walks directory trees and evaluates expressions against each path. It is the right tool when you care about file type, name, size, time or permissions.

find . -type f -name '*.log'
find . -type f -size +10M
find . -type d -name node_modules

Use -exec ... {} + to pass many matched paths to a command in as few invocations as possible.

find . -type f -name '*.md' -exec wc -l {} +

Avoid parsing find output with whitespace-delimited loops. File names can contain spaces, tabs and newlines. Use -print0 with tools that accept null-delimited input.

find . -type f -name '*.log' -print0 | xargs -0 gzip

When the command you are running can be expressed with find itself, prefer that. For example, deletion can be handled directly.

find . -type f -name '*.tmp' -delete

Review destructive find commands with -print before replacing it with -delete. Note that -print0, -delete and -exec ... {} + are widely available but go beyond the base POSIX predicate set, so confirm support if you target unusual systems.

Use ripgrep for code search

ripgrep, usually run as rg, is designed for recursive text search. By default it respects ignore files such as .gitignore when it detects a source control repository, and it skips hidden files and binary files.

rg 'createUser'
rg -n 'createUser' src

Use -S for smart case. It searches case-insensitively when the pattern is all lower case and case-sensitively when the pattern contains an uppercase letter.

rg -S 'userid'

Use -g to include or exclude globs.

rg 'timeout' -g '*.ts'
rg 'timeout' -g '!dist'

Use --hidden when dotfiles matter. The -u flag relaxes filtering in stages: -u stops respecting ignore files, -uu also searches hidden files, and -uuu also searches binary files. Reach for these only when you intentionally want to widen the search.

rg --hidden 'theme' ~/.config

For code review, rg is often faster and quieter than grep -R because the default ignore behaviour matches what developers usually mean by project search.

Use fd for friendly path search

fd is a user-friendly alternative to find for common path searches. It does not aim to implement every find feature. Its defaults are designed for interactive use.

fd config
fd '\.md$'

Like ripgrep, fd respects ignore files by default when searching inside a git repository, and it skips hidden files unless requested otherwise.

fd --hidden ssh ~/.config

Use -e to match file extensions and -x to run a command for each result.

fd -e md -x wc -l

Use find instead of fd in scripts that need POSIX-style availability or advanced predicates. Use fd interactively when its defaults match the question.

Combine tools by responsibility

Use the path tool to choose files, then the content tool to inspect them.

find . -type f -name '*.ts' -exec grep -n 'TODO' {} +

For interactive project search, rg can often do both selection and matching.

rg 'TODO' -g '*.ts'

For exact path selection followed by fast content search, combine null-delimited streams where supported.

fd -0 -e ts | xargs -0 rg -n 'TODO'

Check each tool's null-delimited options before using this pattern. Correct delimiter handling matters more than a shorter command.

Make searches reproducible

Document whether hidden files, ignored files and binary files are included. Many search disagreements come from different defaults, not different data.

Good search commands make scope visible.

rg --hidden -g '!node_modules' 'api_key' .
find . -type f -name '*.pem' -print

Use fixed strings when searching for literal tokens. Use regular expressions when pattern syntax is needed. Mixing the two leads to false positives and missed matches.

Conclusion

Use grep for portable text matching, find for precise filesystem predicates, ripgrep for fast project search and fd for friendly interactive path search. The fastest search is not just the quickest command, it is the command whose scope and matching rules are clear.