ripgrep Command in Linux: Fast Recursive Search

By 

Updated on

12 min read

ripgrep command searching files recursively in a Linux terminal

Searching through a large codebase or a directory full of log files with grep often means adding -r for recursion, -n for line numbers, and --include or --exclude rules to avoid unrelated files. In a Git repository, you may also need extra excludes for build directories, vendor files, and binary output.

ripgrep (rg) handles the common case with better defaults. It searches directories recursively, respects .gitignore, .ignore, and .rgignore rules, skips hidden and binary files during recursive searches, and shows friendly interactive output. It is also much faster than traditional recursive grep on many large file trees because it uses Rust’s regex engine and parallel directory traversal.

This guide explains how to use the ripgrep command in Linux, from basic searches to file type filters, context lines, replacement previews, and config defaults.

What Is the rg Command

The rg command is the executable name for ripgrep, a line-oriented search tool written in Rust and first released by Andrew Gallant in 2016. When people refer to the rg command, they mean ripgrep; the short name exists because the tool is meant to be typed often.

The practical difference from grep is the set of defaults. A plain grep "error" reads standard input; add a filename to search a file. It needs -r to descend into directories, -n to number lines, and --exclude-dir rules to skip directories such as node_modules or .git.

In an interactive terminal, rg "error" searches recursively from the current directory, shows line numbers and colors, skips binary files, and honors the .gitignore rules in a Git repository. If you pipe input to rg, it searches that input instead. Line numbers and colors are disabled by default when you pipe or redirect its output.

Behaviorgreprg
Recursive searchNeeds -rDefault
Line numbers in terminal outputNeeds -nDefault
Respects .gitignoreNoDefault
Hidden filesSearchedSkipped
Binary filesPrints a match noticeSkipped
Parallel directory traversalNoYes

Speed follows from the same design. ripgrep walks directories in parallel and matches with Rust’s regex engine, which compiles a pattern into a finite automaton instead of backtracking, so pathological patterns do not stall the search. Skipping ignored and binary files also means there is less data to read in the first place.

This does not make grep obsolete. POSIX specifies grep, and it is present on every Unix-like system, which matters in portable scripts and on machines where you cannot install extra packages. Reach for rg when you are searching a project interactively, and keep grep for scripts that must run anywhere.

Installing ripgrep

On Ubuntu, Debian, and Derivatives, install the ripgrep package with apt:

Terminal
sudo apt install ripgrep

On Fedora, RHEL, and Derivatives, use dnf. On RHEL and compatible distributions, enable the EPEL repository for your distribution version first:

Terminal
sudo dnf install ripgrep

On Arch Linux, install it from the official repositories:

Terminal
sudo pacman -S ripgrep

Verify the installation with:

Terminal
rg --version

The output shows the installed version:

output
ripgrep 15.2.0 (rev e89fff89ac)

Your distribution may ship a different version, but the examples in this guide use common options available in current ripgrep releases.

Syntax

The basic syntax for the rg command is:

txt
rg [OPTIONS] PATTERN [PATH ...]

The PATTERN argument is the text or regular expression to search for. If you omit PATH, rg searches recursively from the current directory.

For example, rg "error" searches the current directory tree, while rg "error" logs/ limits the search to the logs directory.

Search for a pattern in all files under the current directory:

Terminal
rg "error"

Example output:

output
logs/app.log:42:error: connection refused
logs/app.log:78:error: timeout after 30s
src/main.py:114:raise ValueError("error parsing config")

The output shows the filename, line number, and matching line. In an interactive terminal, rg also uses color by default, so you do not need the usual recursive grep flags for the common code-search workflow.

To search in a specific file, pass the filename after the pattern:

Terminal
rg "error" logs/app.log

To search in a specific directory, pass the directory path:

Terminal
rg "error" logs/

Filtering by File Type

Use -t to restrict the search to a known file type:

Terminal
rg -t py "import os"

This searches only Python files. ripgrep includes built-in definitions for many file types. To see the full list, run:

Terminal
rg --type-list

To exclude a file type, use -T:

Terminal
rg -T js "TODO"

You can also use glob patterns with -g to match or exclude specific filenames. Quote glob patterns so the shell does not expand them before rg receives them:

Terminal
rg -g '*.log' "error"

Use a leading ! to exclude matching paths:

Terminal
rg -g '!*.min.js' "console.log"

The ! prefix belongs to rg, so quoting is especially useful in shells where ! can trigger history expansion.

Add -i to ignore letter case:

Terminal
rg -i "warning"

This matches warning, Warning, WARNING, and other case variants.

For a more flexible default, use -S or --smart-case:

Terminal
rg -S "warning"

With smart case, an all-lowercase pattern is case-insensitive, but a pattern with any uppercase letter is case-sensitive. For example, rg -S "warning" matches Warning, while rg -S "Warning" searches for that exact capitalization.

By default, rg treats the pattern as a regular expression. Use -F to search for a literal string instead, which is useful when the pattern contains regex characters:

Terminal
rg -F "price[0]"

Without -F, [0] would be interpreted as a character class. With -F, rg searches for the literal text price[0].

Counting and Listing Matches

To count matching lines per file instead of printing the matching lines, use -c:

Terminal
rg -c "error"

Example output:

output
logs/app.log:14
logs/nginx/access.log:3

The count is the number of matching lines, not the total number of matching words or strings.

To print only filenames that contain at least one match, use -l:

Terminal
rg -l "error"

To print only filenames that contain no matches, use --files-without-match:

Terminal
rg --files-without-match "error"

This is different from combining -v with -l. The --files-without-match option checks whether a file has zero matching lines.

Context Lines

When a matching line alone is not enough to understand the surrounding code, add context with -C:

Terminal
rg -C 3 "panic"

This prints three lines before and three lines after each match.

Use -A for lines after the match only:

Terminal
rg -A 2 "def connect"

Use -B for lines before the match only:

Terminal
rg -B 2 "def connect"

Context output is useful when you want to inspect the code around a function, error message, or configuration value without opening each file.

Multiple Patterns

Use -e to search for more than one pattern in a single pass:

Terminal
rg -e "error" -e "warning"

This matches any line containing either word. It is equivalent to the regex error|warning, but repeated -e options are easier to read when patterns become longer.

The -e option is also useful when a pattern begins with a dash:

Terminal
rg -e "--force"

Without -e, rg would try to interpret --force as an option.

Whole-Word Match

The -w flag restricts matches to whole words. This is useful when you want to find a variable name without matching it inside a longer name:

Terminal
rg -w "id"

This matches id, but not uid or invalid.

Invert Match

The -v flag prints lines that do not match the pattern:

Terminal
rg -v "^#" config.txt

This shows all lines in config.txt that do not begin with #.

If you want filenames that do not contain a pattern at all, use --files-without-match instead:

Terminal
rg --files-without-match "version" -g '*.json'

Searching Hidden Files and Ignoring .gitignore

By default, recursive rg searches skip hidden files and directories, and respect .gitignore, .ignore, and .rgignore files. This is usually what you want in a source tree.

To include hidden files and directories, use --hidden:

Terminal
rg --hidden "api_key"

To ignore .gitignore, .ignore, and .rgignore rules, use --no-ignore:

Terminal
rg --no-ignore "TODO"

The --no-ignore option does not include hidden files by itself. To search hidden files and ignored files in the same search, combine both options:

Terminal
rg --hidden --no-ignore "password"
Warning
Searching with --hidden --no-ignore can include build artifacts, dependency directories, cache folders, and other large trees. It is much slower and can produce noisy results, so use it only when you have a specific reason to search outside the normal project files.

Replacing Output

The -r option rewrites matching text in the output to show what a replacement would look like. It does not modify any files:

Terminal
rg "foo" -r "bar"

Example output:

output
src/config.py:5:bar = get_setting("bar")

The output shows the line as it would look after replacing foo with bar. This is useful for previewing a project-wide rename before using sed or a text editor’s find-and-replace feature.

For capture groups in replacements, wrap the command in single quotes so the shell does not expand $1, $name, or similar replacement references before rg runs.

Showing Only the Match

By default, rg prints the full line containing the match. Use -o to print only the matched text:

Terminal
rg -o 'v[0-9]+\.[0-9]+\.[0-9]+'

Example output:

output
package.json:4:v1.4.2
package-lock.json:8:v1.4.2

This is useful when you want to extract values from files rather than inspect matching lines in context.

ripgrep Configuration File

ripgrep can read default options from a configuration file, but it does not automatically look in ~/.config/ripgrep/ or any other fixed path. You must point RIPGREP_CONFIG_PATH to the file you want rg to read.

For example, create a config file named ~/.ripgreprc:

~/.ripgreprctxt
--smart-case
--hidden
--glob=!.git/

Then export the environment variable:

Terminal
export RIPGREP_CONFIG_PATH="$HOME/.ripgreprc"

Add that export line to your shell startup file, such as ~/.bashrc or ~/.zshrc, if you want the setting to apply in new terminal sessions.

Each config file line is passed to rg as one command-line argument. For options with values, use either --option=value on one line or put the option and its value on separate lines.

Troubleshooting

rg does not find a file you expected
The file may be hidden, ignored by .gitignore, ignored by .ignore or .rgignore, or detected as binary. Start with rg --debug "pattern" to see why paths were skipped, then add --hidden, --no-ignore, or both only when needed.

A glob pattern does not work as expected
Quote glob patterns, such as rg -g '*.conf' "server" and rg -g '!*.min.js' "console.log". Without quotes, your shell may expand * before rg sees the pattern.

A pattern starting with - is treated as an option
Use -e before the pattern, for example rg -e "--force". You can also use -- to stop option parsing, as in rg -- "--force".

Options Reference

  • -t TYPE - Search only files of the given type.
  • -T TYPE - Exclude files of the given type.
  • -g GLOB - Include or exclude files by glob. A ! prefix excludes paths.
  • -i - Search case-insensitively.
  • -F - Treat the pattern as a fixed string, not a regex.
  • -c - Count matching lines per file.
  • -l - List only filenames with matches.
  • --files-without-match - List only filenames without matches.
  • -C N - Show N lines of context around each match.
  • -A N - Show N lines after each match.
  • -B N - Show N lines before each match.
  • -e PATTERN - Add a search pattern. Repeat it to search for multiple patterns.
  • -w - Match whole words only.
  • -v - Invert the match and print non-matching lines.
  • -o - Print only the matched text, not the full line.
  • -r REPLACEMENT - Show output with matches replaced. This is a preview only.
  • -n - Show line numbers. This is enabled by default in interactive terminal output.
  • --hidden - Search hidden files and directories.
  • --no-ignore - Do not respect .gitignore, .ignore, and .rgignore rules.
  • -S, --smart-case - Search case-insensitively when the pattern is lowercase, and case-sensitively when it contains uppercase.
  • --stats - Print a summary of the search at the end.
  • -M N - Omit lines longer than N bytes.

Quick Reference

For a printable quick reference, see the ripgrep cheatsheet .

TaskCommand
Search recursively from the current directoryrg "pattern"
Search a specific file or directoryrg "pattern" logs/
Search one file type onlyrg -t py "pattern"
Filter by glob, or exclude with !rg -g '*.log' "pattern"
Use smart case matchingrg -S "pattern"
Show three lines of contextrg -C 3 "pattern"
List matching filenamesrg -l "pattern"
Include hidden and ignored filesrg --hidden --no-ignore "pattern"
Preview a replacementrg "old" -r "new"

FAQ

Is rg faster than grep?
On a large directory tree, almost always. ripgrep traverses directories in parallel and skips ignored, hidden, and binary files, so it reads far less data than a recursive grep over the same project. The gap narrows on a single small file with a simple literal pattern, where GNU grep is already close to the speed of reading the file. The default behavior, not raw matching speed alone, is what makes rg feel faster in day-to-day use.

Does the rg command search hidden files?
Not during a recursive search. rg skips dotfiles and dot-directories, and it also honors .gitignore, .ignore, and .rgignore. These are two separate filters: --hidden adds hidden files, and --no-ignore disables the ignore-file rules. The -u flag is shorthand for stacking them, where -u equals --no-ignore, -uu equals --no-ignore --hidden, and -uuu adds binary files as well.

What does rg –files do?
It prints every file rg would search and then exits without searching any of them. This is the quickest way to confirm that a type or glob filter selects what you expect before you run the real search, as in rg --files -t py. Piping it to wc -l gives you a file count for the current filters.

How do I actually replace text with rg?
The -r option only previews a replacement, so you need a second tool to write the change. Preview the affected files first with rg -l "old" ..

Commit or back up the files before running an in-place replacement. Once the file list looks right, pass it to sed :

Terminal
rg -l -0 'old' . | xargs -0 -r sed -i.bak 's/old/new/g'

The -0 options keep filenames containing spaces, quotes, or newlines intact. GNU xargs -r skips the command when no files match, and sed -i.bak saves each original file with a .bak suffix before editing it.

Conclusion

ripgrep covers the same ground as grep , but its recursive search, file filtering, and ignore-file support make it a better default for many code and log searches. For path-based file finding, pair it with find , or use rg -l when you need a list of files that contain a specific pattern.

Linuxize Weekly Newsletter

A quick weekly roundup of new tutorials, news, and tips.

About the authors

Dejan Panovski

Dejan Panovski

Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 1000+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.

View author page