ripgrep Command in Linux: Fast Recursive Search
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.
Installing ripgrep
On Ubuntu, Debian, and Derivatives, install the ripgrep package with apt:
sudo apt install ripgrepOn Fedora, RHEL, and Derivatives, use dnf:
sudo dnf install ripgrepOn Arch Linux, install it from the official repositories:
sudo pacman -S ripgrepVerify the installation with:
rg --versionThe output shows the installed version:
ripgrep 15.1.0 (rev af60c2de9d)
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:
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.
Basic Search
Search for a pattern in all files under the current directory:
rg "error"Example 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:
rg "error" logs/app.logTo search in a specific directory, pass the directory path:
rg "error" logs/Filtering by File Type
Use -t to restrict the search to a known file type:
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:
rg --type-listTo exclude a file type, use -T:
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:
rg -g '*.log' "error"Use a leading ! to exclude matching paths:
rg -g '!*.min.js' "console.log"The ! prefix belongs to rg, so quoting is especially useful in shells where ! can trigger history expansion.
Case-Insensitive Search
Add -i to ignore letter case:
rg -i "warning"This matches warning, Warning, WARNING, and other case variants.
For a more flexible default, use -S or --smart-case:
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.
Fixed String Search
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:
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:
rg -c "error"Example 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:
rg -l "error"To print only filenames that contain no matches, use --files-without-match:
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:
rg -C 3 "panic"This prints three lines before and three lines after each match.
Use -A for lines after the match only:
rg -A 2 "def connect"Use -B for lines before the match only:
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:
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:
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:
rg -w "id"This matches id, but not uid or invalid.
Invert Match
The -v flag prints lines that do not match the pattern:
rg -v "^#" config.txtThis 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:
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:
rg --hidden "api_key"To ignore .gitignore, .ignore, and .rgignore rules, use --no-ignore:
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:
rg --hidden --no-ignore "password"--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:
rg "foo" -r "bar"Example 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:
rg -o 'v[0-9]+\.[0-9]+\.[0-9]+'Example 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:
--smart-case
--hidden
--glob=!.git/Then export the environment variable:
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.rgignorerules. -
-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 .
| Task | Command |
|---|---|
| Search recursively from the current directory | rg "pattern" |
| Search in a specific file | rg "pattern" file.txt |
| Search in a specific directory | rg "pattern" logs/ |
| Search only Python files | rg -t py "pattern" |
| Exclude JavaScript files | rg -T js "pattern" |
| Search by glob | rg -g '*.log' "pattern" |
| Exclude by glob | rg -g '!*.min.js' "pattern" |
| Search case-insensitively | rg -i "pattern" |
| Use smart case | rg -S "pattern" |
| Search for a fixed string | rg -F "price[0]" |
| Count matching lines per file | rg -c "pattern" |
| List matching filenames | rg -l "pattern" |
| List filenames without matches | rg --files-without-match "pattern" |
| Show three lines of context | rg -C 3 "pattern" |
| Search multiple patterns | rg -e "foo" -e "bar" |
| Match a whole word | rg -w "id" |
| Invert line matches | rg -v "pattern" |
| Include hidden files | rg --hidden "pattern" |
| Ignore ignore files | rg --no-ignore "pattern" |
| Include hidden and ignored files | rg --hidden --no-ignore "pattern" |
| Preview replacement output | rg "old" -r "new" |
| Print only matched text | rg -o "pattern" |
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.
![]()