grep and ripgrep Command Builder

Build grep and ripgrep searches with include, exclude and context.

About this tool

Set the pattern, where to look, which files and folders to include or skip, and what to show (lines with context, only matches, counts or file names). Get the matching GNU grep and ripgrep commands with every flag explained, and test the pattern on sample text right in the page.

How to use it

  1. Type what to search for. Several lines become several patterns, any of which can match.
  2. Choose regex, basic, plain text or Perl syntax, and options like ignore case or whole words.
  3. Set where to search and which files and folders to include or skip.
  4. Pick what to show, test the pattern on sample text, then copy the grep or ripgrep command.

Questions

How do I search recursively but skip some folders?
Add --exclude-dir for each folder, for example grep -r --exclude-dir=.git --exclude-dir=vendor pattern . With ripgrep, anything listed in .gitignore is skipped automatically, and -g '!folder/' skips more.
How do I search only certain file types?
With grep, add --include='*.log' (quote it, so the shell doesn’t expand the star). With ripgrep, use -g '*.log' or a built-in type like -t py or -t java.
What is the difference between grep -E and plain grep?
Plain grep uses basic regular expressions, where + ? | ( ) are ordinary characters unless escaped with a backslash. -E switches to extended syntax, where they work as operators, just like in most programming languages.
Should I use grep or ripgrep?
ripgrep (rg) is much faster on large projects, searches recursively by default and respects .gitignore. grep is installed on every Unix system, which matters on servers and in scripts.
How do I show lines around each match?
Use -C 3 for three lines of context on both sides, or -B and -A for before and after separately. The preview here shows the same context lines.
How do I grep for a pattern that starts with a dash?
grep would read it as an option. Put -e in front, as in grep -e "-v" notes.txt, or end the options with two dashes: grep -- "-v" notes.txt. The tool adds -e automatically whenever a pattern starts with a dash.
How do I search inside compressed .gz log files?
Plain grep sees only compressed bytes, which is why *.gz is excluded by default here. Use zgrep, which accepts most grep options, for example zgrep -i "timeout" /var/log/app.log.2.gz. For a whole folder of rotated logs, zgrep -i timeout /var/log/app.log* searches plain and compressed files together.
How do I count matches instead of matching lines?
grep -c counts lines, so a line with three matches counts once. To count every occurrence, print each match on its own line and count those: grep -o "error" app.log | wc -l. Add -i to both counts if the case varies.

How to grep for multiple words

To match lines that contain any of several words, use extended syntax: grep -E "error|warn" app.log. The same works with one -e per pattern, grep -e error -e warn app.log, which is what you get here when you type each pattern on its own line. In basic syntax you would need error\|warn, a GNU extension that BSD grep on macOS may not accept.

grep has no AND operator. To find lines containing both words in any order, pipe one search into another: grep -i payment app.log | grep -i timeout. In GNU grep, -P supports lookaheads, as in grep -P "^(?=.*payment)(?=.*timeout)", but -P is missing from the default grep on macOS. To find files rather than lines that contain both words, chain grep -rl with xargs.

Why does grep find nothing?

First check the quoting. Without quotes the shell expands * and $ before grep sees the pattern, so always wrap it in double quotes, or in single quotes when it contains $. Next check the syntax: in plain grep, + ? and | are ordinary characters unless you add -E. And a dot matches any character, so search for a literal version number with grep -F "1.2.3".

Files with Windows line endings break patterns anchored with $, because every line ends with an invisible carriage return. Match it with grep -P "foo\r?$" or convert the file with dos2unix first. If grep prints “binary file matches”, it found a NUL byte; add -a to search the file as text. Test the pattern on sample text here, or in the Regex Tester, before you run it on real files.

ripgrep equivalents of common grep flags

Most flags are the same in both: -i, -w, -v, -c, -l, -o, -m and the -A, -B and -C context options. The differences catch people out. ripgrep shows line numbers by default in a terminal, so -N hides them. To hide file names, grep uses -h but ripgrep uses -I, and in grep -I means skip binary files. To follow symlinks, grep uses -R and ripgrep uses -L.

ripgrep searches recursively and skips hidden files and anything in .gitignore, so --hidden and --no-ignore turn that off. Instead of --include and --exclude it has one flag: rg -g "*.py" TODO searches only Python files, and a glob starting with ! excludes. The generated command puts that in single quotes, so bash doesn’t treat ! as history. With -S, smart case, a lowercase pattern ignores case and one with capitals doesn’t. grep has no smart case, so the grep command uses -i instead.

Something not working, or a result looks wrong? Report a problem with this tool