rg
Introduction
rg (ripgrep) is a high-performance recursive search tool designed as a modern replacement for grep. It is optimized for speed, usability, and intelligent defaults, making it ideal for searching large codebases, WordPress installations, and log directories on VPS systems.
Tool Snapshot
- Core Function: Ultra-fast recursive search engine for file content.
- Primary Benefit: Rust-powered speed with automatic filtering of ignored/hidden files.
- Where to Use: Massive log analysis, malware triage, and large-scale code audits.
- Key Feature: High-performance regex engine and JSON output support.
Unlike traditional grep, rg:
- Searches recursively by default
- Respects
.gitignore,.ignore, and.rgignore - Skips hidden and binary files unless explicitly enabled
- Uses a fast regex engine (Rust regex by default)
- Supports advanced PCRE2 patterns (when compiled with PCRE2)
- Can search inside compressed files
- Provides structured JSON output for automation
For sysadmins and developers, rg is especially effective for:
- Malware and obfuscation detection
- Log analysis
- Code auditing
- Configuration troubleshooting
- Incident response investigations
Prerequisites
- Ubuntu/Debian or similar Linux VPS
- SSH access
- WordPress paths you should know:
/var/www/html/→ WordPress root/var/www/html/wp-content/uploads/→ Media/home/backups/→ Backups
Install and verify:
sudo apt install ripgrep
rg --version
Syntax & Expression Rules
The command follows a logical structure that reads almost like a sentence:
rg [OPTIONS] PATTERN [PATH...]
[OPTIONS]: Flags to modify search (e.g.,-ifor case-insensitive,-tfor file type).[PATTERN]: The regex or fixed string to search for.[PATH]: One or more directories or files to search (defaults to current directory).
Multiple patterns
rg -e PATTERN1 -e PATTERN2 [PATH...]
Patterns from file
rg -f patterns.txt [PATH...]
Pattern Engine
- Default engine: Rust regex (fast, safe, no catastrophic backtracking)
- Enable PCRE2 (lookaround, backreferences) with:
rg -P 'pattern'
PCRE2 support depends on how ripgrep was compiled.
How rg Handles Scope
-
If no path is provided,
rgsearches the current directory. -
If specific files are provided explicitly, ignore rules are bypassed.
-
By default:
- Hidden files are skipped
- Binary files are skipped
.gitignorerules are respected
Control filtering with:
--hidden-u,-uu,-uuu--no-ignore
Important Filters and Options
| Option | Description | WordPress/VPS Use Case | Example |
|---|---|---|---|
| -- | - | ||
-F | Fixed string (no regex) | Literal malware signature | rg -F 'base64_decode(' -t php |
-i | Ignore case | Case-insensitive search | rg -i logo |
-S | Smart case | Case-sensitive only if uppercase used | rg -S logo |
-t TYPE | Limit by file type | Only PHP files | rg -t php add_action |
--type-list | Show supported types | View available filters | rg --type-list |
-g GLOB | Include/exclude via glob | Skip vendor directory | rg -g '!vendor/**' |
--iglob | Case-insensitive glob | Match *.JPG | rg --iglob '*.jpg' |
--hidden | Include hidden files | Search .env files | rg --hidden token |
-u/-uu/-uuu | Relax ignore rules | Full forensic scan | rg -uuu password |
-L | Follow symlinks | Deployment releases | rg -L -t php add_action |
--one-file-system | Stay within filesystem | Avoid NFS mounts | rg --one-file-system error /var |
-z | Search compressed files | Inspect backups | rg -z ERROR /home/backups |
--encoding | Specify encoding | Legacy logs | rg --encoding latin1 pattern |
-U | Enable multiline | Cross-line patterns | rg -U 'BEGIN.*END' |
--multiline-dotall | . matches newline | Full block matching | rg -U --multiline-dotall 'A.*Z' |
Most Important Filters (Practical Ranking)
| Filter | Rating | Why It Matters |
|---|---|---|
| -- | -- | |
-t TYPE | 5/5 | Massive noise reduction in codebases |
-g | 5/5 | Precise include/exclude control |
-F | 4/5 | Faster and safer for literal search |
--hidden + -u | 4/5 | Critical for audits and incident response |
-P | 3/5 | Required only for advanced regex features |
Output and Action Controls
| Option | Purpose | Example |
|---|---|---|
| -- | - | - |
-n | Show line numbers | rg -n error |
-H | Always show filename | rg -nH error |
-l | Filenames only | rg -l base64 |
-c | Count matches per file | rg -c wp_enqueue |
-v | Invert match | rg -v DEBUG app.log |
-o | Print only match text | rg -o 'https?://\S+' |
-C NUM | Show context | rg -C2 ERROR |
--vimgrep | Editor-friendly output | rg --vimgrep TODO |
--json | Structured output | rg --json pattern |
--stats | Show search stats | rg --stats pattern |
When piping results, force consistent output:
rg -nH --color=never pattern
Benefits
- Extremely fast recursive search
- Smart filtering by default
- Respects project ignore rules
- Powerful type system for languages
- JSON output for automation
- Compressed file search
- Advanced regex support (PCRE2 optional)
Best Practices
- Narrow scope early with
-tand-g. - Use
-Ffor fixed strings unless regex is required. - Add
-nHwhen piping to other tools. - Use
--hiddenand-uuduring security audits. - Use
-Ponly when you need lookaround or backreferences. - Combine
--jsonwithjqfor structured automation.
Cheat Sheet
# Basic recursive search
rg pattern
# Force filename and line numbers
rg -nH pattern
# Fixed string search
rg -F 'literal text'
# File type filtering
rg -t php add_action
# Exclude heavy directories
rg -g '!vendor/**' -g '!node_modules/**'
# Include hidden files
rg --hidden -uu secret
# Count matches
rg -c pattern
# Show only filenames
rg -l pattern
# Context lines
rg -C3 ERROR
# PCRE2 lookbehind (if supported)
rg -P '(?<=foo)bar'
# Multiline search
rg -U --multiline-dotall 'BEGIN.*END'
# Search inside compressed backups
rg -z ERROR /home/backups
# JSON output for automation
rg --json pattern | jq .
Troubleshooting Matrix
| Problem | Cause | Solution |
|---|---|---|
| -- | - | |
| No results | Hidden or ignored files | Add --hidden or -uu |
| No line numbers in pipe | Non-TTY output | Add -nH |
| Lookaround not working | PCRE2 not enabled | Use -P and verify build |
| Globs case-sensitive | Default glob behavior | Use --iglob |
| Multiline regex fails | . doesn’t match newline | Add -U --multiline-dotall |
| Too many results | Scope too broad | Add -t or -g filters |
WordPress / VPS Examples
1. Malware triage in PHP
rg -nH -t php -g '!vendor/**' -e 'base64_decode' -e 'eval\s*\(' /var/www/html
2. Search Nginx logs for 5xx errors
rg -n 'HTTP/1\.1" 5\d\d' /var/log/nginx
3. Count enqueue usage in themes
rg -c -t php 'wp_enqueue' /var/www/html/wp-content/themes
4. Detect PHP inside uploads (suspicious)
rg -l -t php --hidden -g 'wp-content/uploads/**' .
5. Search inside compressed backups
rg -z 'DROP TABLE' /home/backups
Mini Quiz
- What does
-uuenable compared to default search? - When do you need
-P? - How do you exclude heavy directories?
- How do you search inside compressed files?
- Which options force filenames and line numbers when piping?