Basics of rg

rg is ripgrep, a fast command-line tool for searching text inside files and directories.

rg "pattern"

Search recursively from the current directory.

rg "hello"

Search for hello in files below the current directory.

Search a specific directory

rg "pattern" src/

Search a specific file

rg "pattern" file.txt
rg -i "pattern"
rg -i "hello"

Matches:

hello
Hello
HELLO

Match whole words

rg -w "word"

Matches word but not:

words
password
wording

Show line numbers

rg -n "pattern"

-n is usually enabled by default when output goes to the terminal.

Show only filenames

rg -l "pattern"

Useful for finding which files contain a match.

Show files without matches

rg -L "pattern"

Count matches

rg -c "pattern"

Example:

rg -c "TODO" src/

Search specific file types

rg "pattern" -t js
rg "pattern" -t ts
rg "pattern" -t py

List supported types:

rg --type-list

Search by file extension

rg "pattern" -g "*.ts"
rg "pattern" -g "*.css"

Exclude files

rg "pattern" -g '!*.min.js'

Exclude a directory:

rg "pattern" -g '!node_modules'

Search hidden files

By default, rg skips hidden files.

rg --hidden "pattern"

Search hidden files and ignored files

rg --no-ignore "pattern"

Combine them:

rg --hidden --no-ignore "pattern"

Search only the current directory

rg --max-depth 1 "pattern"

Search with regular expressions

rg supports regular expressions.

rg "foo|bar"
rg "user_[0-9]+"

Literal search:

rg -F "foo.bar"

-F disables regex interpretation.

Search for exact text

rg -F "foo.bar"

Useful when the search contains regex characters such as:

.
*
+
?
[
]
(
)

Invert matches

Find lines that don’t match:

rg -v "pattern"

Context around matches

Show lines before a match:

rg -B 2 "pattern"

Show lines after a match:

rg -A 2 "pattern"

Show both:

rg -C 2 "pattern"

Search filenames

rg --files

List files known to rg.

Filter them:

rg --files | rg '\.ts$'

Search Git-tracked files

rg automatically respects .gitignore.

rg "pattern"

To ignore Git’s ignore rules:

rg --no-ignore "pattern"

Search from the parent directory

rg "pattern" ..

Search multiple directories

rg "pattern" src/ tests/

Replace text

rg itself does not modify files.

A common workflow is:

rg "old" .

Then use another tool for replacement, such as sed or perl.

For example:

rg -l "old" . | xargs sed -i 's/old/new/g'

Be careful with bulk replacements.

Useful options

Option Meaning
-i Case-insensitive
-w Whole-word match
-F Fixed string, no regex
-v Invert match
-l Show matching filenames
-L Show non-matching filenames
-c Count matches per file
-n Show line numbers
-A N Show N lines after
-B N Show N lines before
-C N Show N lines of context
-g Glob filter
-t File type filter
--hidden Include hidden files
--no-ignore Don’t respect ignore files
--files List searchable files
--max-depth N Limit directory depth

Common recipes

Find TODOs:

rg "TODO"

Find a function:

rg "function foo"

Find imports:

rg "^import "

Search TypeScript files:

rg "useState" -t ts -t tsx

Find files containing a string:

rg -l "DATABASE_URL"

Search case-insensitively:

rg -i "error"

Search an exact string:

rg -F "foo.bar()"

Search including hidden files:

rg --hidden "pattern"

List all files:

rg --files

rg vs grep

Traditional:

grep -R "pattern" .

With rg:

rg "pattern"

rg is generally faster and has convenient defaults for modern projects, including recursive searching and respecting .gitignore.

The essentials

rg "pattern"              # search
rg -i "pattern"           # case-insensitive
rg -F "text"              # literal text
rg -w "word"              # whole word
rg -l "pattern"           # filenames only
rg -c "pattern"           # count
rg -t ts "pattern"        # file type
rg -g "*.ts" "pattern"    # glob
rg --hidden "pattern"     # include hidden files
rg --no-ignore "pattern"  # include ignored files
rg --files                # list files
rg -C 2 "pattern"         # surrounding context