Tldr:
- Grep is good but can be slow, especially when searching large codebases
- Try
ripgrep
. It’s much faster and has convenient defaults
Grep
In large codebases just finding the things you need can be hard. The built-in solution on linux/unix is grep
. The basic format is grep {search_term} {file_path}
. Here are a few simple examples:
# This searches for the string "justin" in the file "package.json"
grep justin package.json
# Grep is case-sensitive by default, -i makes it case-insensitive
# So this will find "justin", "Justin", or "JUSTIN"
grep -i justin package.json
# Searches for "justin" in all files in my current directory
grep justin ./*
# "-r" means this will recursively search all directories
# which are children of the current directory.
# This one might take a while
grep -r justin ./*
Here are a few commonly-used useful flags for grep:
Flag | Effect |
---|---|
-i | makes search case-insensitive |
-r | recursively search directories |
-n | show the line number within the file where the match occurs |
-l | return only the names of files where matches were found |
A quick example combining flags to search the infamous /node_modules
directory:
pwd
# /repo/node_modules
# This will print every file name within /node_modules which
# contains a match for the string "justin", case-insensitive
grep -irl justin ./*
When doing a search like this, however, grep is slow. I timed the search above via command line time
and it took 34.3s
, which is more than enough time to get distracted. I ran the same search with ripgrep and it finished in 3.4s
; 10 times faster.
Ripgrep
Ripgrep
is an open source alternative to grep, and it is fast.1 I used to worry about optimizing my grep searches to try and speed them up. With rg
, I don’t even consider optimization, it’s pointless. Besides winning on speed, ripgrep also bakes in some convenient default search behavior:
- Searches the current directory without needing an additional argument
- Searches sub-directories, no
-r
flag needed - Ignores anything in your
.gitignore
, hidden files, and binary files - Has nicely organized and colorized output, for easier reading
Here’s my local output when running the same query in grep
and then again in ripgrep
. First, grep:
Now here’s ripgrep (rg
). This is the same exact search, but rg
doesn’t require the additional -i
and -r
flags, or the *
telling it to search this directory:
Helpful Ripgrep configuration options
In the previous paragraph I mentioned that ripgrep doesn’t require the -i
flag, but that’s not entirely true; I just have ripgrep set to --smart-case
2 by default. Ripgrep supports a lot of configuration options, including the ability to specify a RIPGREP_CONFIG_PATH
pointing to a file containing default options you want all the time. Here’s what’s in my config file, which I lifted directly from the example in the docs:
# Don't let ripgrep vomit really long lines to my terminal, and show a preview.
--max-columns=150
--max-columns-preview
# default all searches to smart case
--smart-case
ZshRipgrep also supports just about every native grep
flag. I often use -B
or -A
to show lines before and after a match for more context.
Conclusion
Grep is useful but slow. There are many open source alternatives to grep, but so far I haven’t found anything that beats ripgrep
for pure speed and usability.
Notes
- Ripgrep’s README has a number of performance comparisons to other grep-like tools โฉ๏ธ
- Smart case means: “if the entire string is lowercase, the search is case-insensitive. If anything is uppercased, the search is now case-sensitive.” Just like Vim’s
:set smartcase
โฉ๏ธ
Helpful Links