Skip to content

Automatic Filtering

When you run rg recursively, ripgrep automatically filters out many files and directories to make searches faster and more relevant. This chapter explains ripgrep's automatic filtering mechanisms and how to control them.

Overview

By default, ripgrep respects various ignore files, skips hidden files and directories, and avoids searching binary files. This behavior makes searches faster and reduces noise in results. Understanding these filters helps you search effectively and know when to disable them.

flowchart TD
    Start[File Encountered] --> Explicit{"Specified
Explicitly?"}
    Explicit -->|Yes| Search[Search File]
    Explicit -->|No| Hidden{"Hidden
File?"}

    Hidden -->|Yes| HiddenFlag{"--hidden
enabled?"}
    HiddenFlag -->|No| Skip1[Skip File]
    HiddenFlag -->|Yes| Ignore

    Hidden -->|No| Ignore{"Matches
Ignore Pattern?"}

    Ignore -->|Yes| IgnoreFlag{"--no-ignore
or -u?"}
    IgnoreFlag -->|No| Skip2[Skip File]
    IgnoreFlag -->|Yes| Binary

    Ignore -->|No| Binary{"Binary
Content?"}

    Binary -->|Yes| BinaryFlag{"--binary
enabled?"}
    BinaryFlag -->|No| Skip3[Skip File]
    BinaryFlag -->|Yes| Search

    Binary -->|No| Search

    style Search fill:#e8f5e9
    style Skip1 fill:#ffebee
    style Skip2 fill:#ffebee
    style Skip3 fill:#ffebee
    style Start fill:#e1f5ff

Figure: Ripgrep's automatic filtering decision flow. Files specified explicitly bypass most filters.

Ignore Files

Ripgrep automatically respects several types of ignore files during recursive search:

Supported Ignore File Types

.ignore files: Ripgrep-specific ignore files with the same syntax as .gitignore. These have the highest precedence.

.gitignore files: Standard Git ignore files used by version control systems.

.git/info/exclude files: Repository-specific Git ignore files not committed to the repository.

Global gitignore: Your global Git ignore file, typically located at $XDG_CONFIG_HOME/git/ignore or ~/.config/git/ignore.

.rgignore files: Legacy ripgrep ignore files (replaced by .ignore).

Example Usage

Create a .ignore file to exclude specific patterns:

# Ignore all log files
*.log

# Ignore node_modules directory
node_modules/

# Ignore temporary files
tmp/
*.tmp

Now when you search, these patterns are automatically excluded:

$ rg 'TODO'
# Searches all files except those matching .ignore patterns
Common .ignore Patterns by Project Type
# Dependencies
node_modules/
bower_components/

# Build outputs
dist/
build/
*.bundle.js

# Package manager
package-lock.json
yarn.lock

# Logs and temp
*.log
.cache/
# Build artifacts
target/
Cargo.lock

# IDE files
.idea/
*.swp
*.swo

# Test coverage
tarpaulin-report.html
# Virtual environments
venv/
env/
.venv/

# Bytecode
__pycache__/
*.pyc
*.pyo

# Distribution
dist/
build/
*.egg-info/
# Version control
.git/
.svn/

# OS files
.DS_Store
Thumbs.db

# Editor files
*.swp
*~
.vscode/
.idea/

Precedence Rules

When multiple ignore files exist, ripgrep applies them in a specific order:

  1. .ignore files override all .gitignore files, regardless of directory hierarchy
  2. Within each ignore file type, more nested files have higher precedence
  3. Parent directory ignore files are respected by default
flowchart TD
    Start[File Pattern Match Check] --> Ignore[".ignore files
    (ripgrep-specific)"]
    Ignore -->|Not matched| GitIgnore[".gitignore files
    (nested > parent)"]
    GitIgnore -->|Not matched| Exclude[".git/info/exclude
    (repository-specific)"]
    Exclude -->|Not matched| Global["Global gitignore
    (~/.config/git/ignore)"]
    Global -->|Not matched| Custom["Custom ignore files
    (--ignore-file)"]

    Ignore -->|Matched| Decision{Whitelist
    pattern?}
    GitIgnore -->|Matched| Decision
    Exclude -->|Matched| Decision
    Global -->|Matched| Decision
    Custom -->|Matched| Decision

    Decision -->|"Yes (!pattern)"| Include[Include File]
    Decision -->|No| Skip[Skip File]
    Custom -->|Not matched| Include

    style Ignore fill:#e1f5ff
    style GitIgnore fill:#fff3e0
    style Exclude fill:#fff9c4
    style Global fill:#f3e5f5
    style Custom fill:#fce4ec
    style Include fill:#e8f5e9
    style Skip fill:#ffebee

Figure: Ignore file precedence hierarchy. Higher-priority files can override lower-priority ones. Whitelist patterns (!) in any file can override earlier exclusions.

For example, if you have: - /project/.gitignore with *.log - /project/subdir/.ignore with !important.log

The .ignore file's whitelist pattern (!important.log) will override the .gitignore pattern, allowing important.log to be searched even in the root directory.

Within the same ignore file type: - /project/subdir/.gitignore overrides /project/.gitignore for files in subdir/

Whitelist Patterns

You can use the ! prefix in ignore files to whitelist paths, overriding earlier ignore rules:

# In .gitignore
*.log

# Except this specific log file
!important.log

# Whitelist an entire directory
!logs/keep/

Whitelist Patterns in Action

Scenario 1: Whitelisting specific files in ignored directory

.gitignore:

# Ignore all of node_modules
node_modules/

# Except keep the README for a specific package
!node_modules/critical-package/README.md

Before whitelist:

$ rg --files | grep node_modules
# (no results - all of node_modules ignored)

After whitelist:

$ rg --files | grep node_modules
node_modules/critical-package/README.md

Scenario 2: Cross-file whitelist override

/project/.gitignore:

*.log
build/

/project/important/.ignore:

# Override parent .gitignore for this directory
!debug.log
!build/

Result:

$ rg --files important/
important/debug.log        # Whitelisted despite *.log in parent
important/build/output.txt # Whitelisted despite build/ in parent
important/other.txt

Scenario 3: Whitelist with nested patterns

.ignore:

# Ignore all test directories
**/test/

# But keep integration tests
!**/test/integration/

# And keep specific critical test file
!**/test/critical_test.rs

Whitelist Override Power

Whitelist patterns in .ignore files can override exclusions from .gitignore files, even in parent directories. This makes .ignore files powerful for project-specific ripgrep configurations without modifying your Git settings.

VCS and Global Ignore Files

Ripgrep respects VCS-specific ignore files:

  • .git/info/exclude: Repository-specific patterns not in .gitignore
  • Global gitignore: System-wide patterns from your Git configuration

These can be disabled with --no-ignore-vcs and --no-ignore-global:

$ rg 'pattern' --no-ignore-vcs
# Ignores .gitignore and .git/info/exclude

$ rg 'pattern' --no-ignore-global
# Ignores global gitignore only

Custom Ignore Files

Use --ignore-file to add custom ignore file paths:

$ rg 'pattern' --ignore-file /path/to/custom-ignore

Custom ignore files: - Have the lowest precedence (below all standard ignore files) - Are never disabled by --no-ignore - Can be specified multiple times

Git Repository Requirements

By default, .gitignore files are only respected inside Git repositories. Use --no-require-git to respect .gitignore files even outside repositories:

$ rg 'pattern' --no-require-git

The default behavior can be made explicit with --require-git, which ensures .gitignore files are only respected inside Git repositories.

Hidden Files

Ripgrep skips hidden files and directories by default.

What is Hidden?

A file or directory is considered hidden if: - Its name starts with a dot (.), like .bashrc or .config/ - On Windows, it has the "hidden" file attribute set

Searching Hidden Files

Use -./--hidden to search hidden files:

$ rg 'pattern' --hidden
# Searches all files including .bashrc, .git/, etc.

Hidden Directories and Version Control

--hidden will search inside directories like .git/ regardless of --no-ignore-vcs. To exclude such paths when using --hidden, you must explicitly ignore them:

$ rg 'pattern' --hidden --glob '!.git/'
# Search hidden files but exclude .git directory

Explicit Hidden Files

Hidden files specified directly on the command line are always searched, even without --hidden:

$ rg 'pattern' .bashrc
# Searches .bashrc even though it's hidden

Binary Files

Ripgrep automatically detects and skips binary files during recursive search.

Binary Detection

Ripgrep uses a NUL byte (\0) heuristic: - If a file contains a NUL byte in the first few kilobytes, it's considered binary - Binary detection only applies during recursive search - Files specified directly are always searched

Binary Detection Scope

Binary filtering only applies to recursive search. When you specify a file directly on the command line, ripgrep searches it regardless of content. Use --no-binary to force binary detection for explicit files.

Search binary files with --binary or -a/--text:

$ rg 'pattern' --binary
# Searches all files including detected binary files

Force binary detection with --no-binary:

$ rg 'pattern' file.exe --no-binary
# Skip file.exe if it contains NUL bytes

Note: Binary filtering only applies to recursive search. When you specify a file directly, it's searched regardless of content.

Parent Directory Ignore Files

By default, ripgrep reads ignore files from parent directories of each searched path. This ensures that ignore rules are consistently applied across the directory tree.

Disable this with --no-ignore-parent:

$ rg 'pattern' --no-ignore-parent
# Only respect ignore files in or below current directory

By default, ripgrep does not follow symbolic links during recursive search.

Use -L/--follow to follow symbolic links:

$ rg 'pattern' --follow
# Follows symlinks to files and directories

Loop Prevention

Ripgrep automatically detects and prevents infinite loops when following symlinks that create circular directory structures. It's safe to use --follow even in complex directory trees.

When following symlinks with --follow, ignore files are still respected: - The symlink target is subject to ignore rules in its actual location - If a symlinked directory contains .gitignore or .ignore files, they apply to files within that directory

To follow symlinks while bypassing ignore files:

$ rg 'pattern' --follow --no-ignore
# Follow symlinks and ignore all ignore files

Disabling Automatic Filtering

Ripgrep provides several ways to disable automatic filtering.

Choosing the Right Flag: Decision Tree

Do you need to search ignored files?
├─ Yes, and also hidden files?
│  │
│  ├─ Yes, and also binary files?
│  │  └─ Use: -uuu (or --no-ignore --hidden --binary)
│  │
│  └─ No, just ignored + hidden
│     └─ Use: -uu (or --no-ignore --hidden)
├─ Yes, just ignored files
│  └─ Use: -u (or --no-ignore)
└─ No, but need hidden files?
   ├─ Yes → Use: --hidden
   └─ No, just need specific control?
      └─ Use: --no-ignore-vcs / --no-ignore-dot / etc.

Progressive Unrestricted Flags

The -u/--unrestricted flag can be used up to three times for progressive filtering removal:

graph LR
    Default["Default
rg 'pattern'"] --> U1["-u
--no-ignore"]
    U1 --> U2["-uu
+ --hidden"]
    U2 --> U3["-uuu
+ --binary"]

    Default -.->|Filters| F1["Ignore Files
Hidden Files
Binary Files"]
    U1 -.->|Filters| F2["Hidden Files
Binary Files"]
    U2 -.->|Filters| F3[Binary Files]
    U3 -.->|Filters| F4[None]

    style Default fill:#ffebee
    style U1 fill:#fff3e0
    style U2 fill:#e1f5ff
    style U3 fill:#e8f5e9

Figure: Progressive filter removal with -u flags. Each level disables more filters.

-u (once): Disable ignore files (.gitignore, .ignore, etc.)

$ rg 'pattern' -u
# Same as --no-ignore

-uu (twice): Disable ignore files + search hidden files

$ rg 'pattern' -uu
# Same as --no-ignore --hidden

-uuu (three times): Disable ignore files + search hidden files + search binary files

$ rg 'pattern' -uuu
# Same as --no-ignore --hidden --binary

Fine-Grained Control

For more precise control, use specific --no-ignore-* flags:

Flag Effect
--no-ignore Disable all standard ignore files
--no-ignore-dot Disable .ignore and .rgignore files only
--no-ignore-vcs Disable .gitignore and .git/info/exclude only
--no-ignore-exclude Disable .git/info/exclude only
--no-ignore-global Disable global gitignore only
--no-ignore-parent Don't read ignore files from parent directories
--no-ignore-files Disable custom ignore files from --ignore-file

Combining Fine-Grained Flags

Scenario: Search hidden config files but skip Git files

$ rg 'api_key' --no-ignore-vcs --hidden
# Searches .env, .bashrc, etc., but respects .ignore files

Scenario: Ignore only global gitignore, keep everything else

$ rg 'TODO' --no-ignore-global
# Respects .gitignore and .ignore, but not ~/.config/git/ignore

Scenario: Custom ignore files without standard ones

$ rg 'pattern' --no-ignore --ignore-file team-ignores.txt
# Only respects team-ignores.txt, not .gitignore or .ignore

Scenario: Parent directory patterns interfering

$ rg 'pattern' subdir/ --no-ignore-parent
# Only respects ignore files in or below subdir/

Ignore File Error Handling

By default, ripgrep reports errors when ignore files are malformed. Suppress these messages with --no-ignore-messages:

$ rg 'pattern' --no-ignore-messages
# Silently skip malformed ignore files

Malformed Ignore Files

If ripgrep reports errors about ignore file syntax, it will skip the problematic patterns but continue searching. Use --no-ignore-messages to suppress these warnings, but be aware that some patterns may not be applied.

Common ignore file issues: - Invalid regex patterns (when using regex mode) - Incomplete glob patterns (e.g., unclosed brackets) - Invalid escape sequences

Always test your ignore files with rg --files to verify they work as expected.

Case Insensitive Ignore Files

On Windows or case-insensitive filesystems, you may want case-insensitive glob matching in ignore files. Use --ignore-file-case-insensitive:

$ rg 'pattern' --ignore-file-case-insensitive
# *.LOG in ignore file will match file.log

Interaction with Explicit Paths

Files and directories specified explicitly on the command line bypass automatic filtering:

$ rg 'pattern' ignored-file.txt
# Searches ignored-file.txt even if it's in .gitignore

Explicit Path Behavior

Files bypass all filters:

$ rg 'pattern' .bashrc          # Searches hidden file
$ rg 'pattern' ignored.txt      # Searches ignored file
$ rg 'pattern' binary.exe       # Searches binary file

Directories still apply filters:

$ rg 'pattern' some-dir/
# Applies ignore rules to files inside some-dir/

This applies to: - Files listed in .gitignore or .ignore - Hidden files (when --hidden is not used) - Binary files (during recursive search)

Interaction with Manual Filtering

Automatic filtering works alongside manual filtering options like --glob and --type. The filters are combined:

$ rg 'pattern' --type rust --hidden
# Search Rust files, including hidden ones, respecting ignore files

All filtering mechanisms are applied: 1. Glob overrides from --glob 2. Ignore files (.gitignore, .ignore, etc.) 3. File type filters (--type) 4. Hidden file filtering (unless --hidden) 5. Binary file filtering (unless --binary)

See the Manual Filtering: Globs and Manual Filtering: Types chapters for more details.

Common Use Cases

Quick Reference: Common Scenarios

Including hidden and binary files:

$ rg 'pattern' -uuu

Search hidden files but respect .gitignore:

$ rg 'pattern' --hidden

Ignore Git files but use custom ignore file:

$ rg 'pattern' --no-ignore-vcs --ignore-file my-ignores.txt

Search a specific file even if ignored:

$ rg 'pattern' node_modules/package/file.js

Search without .gitignore but with .ignore:

$ rg 'pattern' --no-ignore-vcs

Troubleshooting

Files Are Being Ignored Unexpectedly

  1. Check if the file matches an ignore pattern:

    $ rg --files | grep filename
    # If missing, the file is being filtered
    

  2. Use --debug to see why files are ignored:

    $ rg 'pattern' --debug 2>&1 | grep filename
    

Understanding --debug Output

The --debug flag shows detailed filtering information. Here's what the output looks like:

$ rg 'TODO' --debug 2>&1 | head -20
DEBUG|grep_regex::literal|crates/regex/src/literal.rs:58: literal prefixes detected: Literals { lits: [Complete(TODO)], limit_size: 250, limit_class: 10 }
DEBUG|globset|crates/globset/src/lib.rs:102: built glob set; 0 literals, 3 basenames, 1 extensions, 0 prefixes, 0 suffixes, 0 required extensions, 0 regexes
DEBUG|ignore::walk|crates/ignore/src/walk.rs:1450: ignore file found: .gitignore
DEBUG|ignore::walk|crates/ignore/src/walk.rs:1450: ignore file found: .ignore
DEBUG|ignore::walk|crates/ignore/src/walk.rs:2134: ignoring ./target: Ignore(IgnoreMatch(Gitignore(Glob { from: Some(".gitignore"), original: "/target", actual: "target", is_whitelist: false, is_only_dir: false })))
DEBUG|ignore::walk|crates/ignore/src/walk.rs:2134: ignoring ./node_modules: Ignore(IgnoreMatch(Gitignore(Glob { from: Some(".gitignore"), original: "node_modules/", actual: "node_modules", is_whitelist: false, is_only_dir: true })))
DEBUG|ignore::walk|crates/ignore/src/walk.rs:2134: ignoring ./.git: Ignore(IgnoreMatch(Gitignore(Glob { from: Some(".gitignore"), original: ".git/", actual: ".git", is_whitelist: false, is_only_dir: true })))

Key information in debug output: - ignore file found: Which ignore files were discovered - ignoring ./path: Which files/directories are being filtered - from: Some(".gitignore"): Which ignore file contains the pattern - original: "target": The original pattern from the ignore file - is_whitelist: false: Whether this is a whitelist (!) or ignore pattern - is_only_dir: true: Whether the pattern only matches directories

  1. Try disabling ignore files progressively:
    $ rg 'pattern' -u      # Disable ignore files
    $ rg 'pattern' -uu     # Also search hidden
    $ rg 'pattern' -uuu    # Also search binary
    

Hidden Files Aren't Being Searched

Ensure you're using --hidden or specifying the file directly:

$ rg 'pattern' --hidden           # Search all hidden files
$ rg 'pattern' .config/file.conf  # Search specific hidden file

Binary Files Are Being Searched

If you don't want binary files, ensure you're not using --binary or -uuu:

$ rg 'pattern'  # Binary files skipped by default in recursive search

Ignore Files Aren't Being Respected

Check if you've accidentally disabled them:

$ rg 'pattern'  # Default: ignore files enabled
# Not: rg 'pattern' --no-ignore

Verify ignore file syntax matches .gitignore format.

Summary

Ripgrep's automatic filtering makes searches fast and relevant by: - Respecting .ignore, .gitignore, and other ignore files with clear precedence rules - Skipping hidden files and directories by default - Detecting and skipping binary files during recursive search - Providing progressive -u/-uu/-uuu flags and fine-grained --no-ignore-* options for control

Understanding these filters helps you search effectively and know when to use flags like --hidden, --binary, or -uuu to broaden your search.