Open-Source Wikis

/

fd

/

Systems

/

Ignore rules

sharkdp/fd

Ignore rules

Active contributors: sharkdp, tmccombs, tavianator

Purpose

fd ignores hidden directories and files by default, and respects .gitignore, .ignore, .fdignore, and a global ignore file. This page explains exactly which files are read, in what order, and which CLI flag maps to which behaviour. The actual matching logic lives in the ignore crate (the same one that backs ripgrep). fd's contribution is the configuration glue.

Files fd reads

In order of precedence (closer-to-the-file wins):

  1. -E/--exclude patterns from the command line. Wired in via OverrideBuilder in WorkerState::build_overrides (src/walk.rs).
  2. .gitignore in the current and ancestor directories, plus the global gitignore (~/.config/git/ignore) and .git/info/exclude. Honoured when Config::read_vcsignore is true and either .git/ is present or --no-require-git was passed.
  3. .ignore (the ripgrep-style file) in the same locations, when Config::read_fdignore is true.
  4. .fdignore in the same locations, registered with WalkBuilder::add_custom_ignore_filename(".fdignore") when Config::read_fdignore is true.
  5. Global fdignore at ${etcetera::config_dir()}/fd/ignore (typically ~/.config/fd/ignore on Linux/macOS or %APPDATA%\fd\ignore on Windows). Loaded by WalkBuilder::add_ignore in WorkerState::build_walker. Disabled by --no-global-ignore-file.
  6. Custom ignore files passed with --ignore-file PATH. Loaded by the same add_ignore call as the global file.
  7. Hidden files (names starting with .) are skipped when Config::ignore_hidden is true.

The ignore crate enforces normal .gitignore semantics: deeper rules override shallower ones, !pattern re-includes a previously-excluded file, etc.

Flags and their effects

Flag Effect on Config
-H, --hidden ignore_hidden = false.
--no-hidden Override that resets --hidden.
-I, --no-ignore read_fdignore = false, read_vcsignore = false, read_global_ignore = false.
--ignore Override that resets --no-ignore.
--no-ignore-vcs read_vcsignore = false only.
--no-require-git require_git_to_read_vcsignore = false. By default fd only honours git-related ignore rules inside a git repository. With this flag, gitignore-style rules apply everywhere.
--require-git Override.
--no-ignore-parent read_parent_ignore = false. Stops fd from walking up to ancestor directories looking for ignore files.
--ignore-parent (currently in the Unreleased section of CHANGELOG.md, PR #1958) override that resets --no-ignore-parent.
--no-global-ignore-file read_global_ignore = false only.
-u, --unrestricted Counted alias for --no-ignore --hidden. -uu is a habit-friendly idiom borrowed from ripgrep.

The combinations above are encoded in construct_config (src/main.rs):

ignore_hidden: !(opts.hidden || opts.rg_alias_ignore()),
read_fdignore: !(opts.no_ignore || opts.rg_alias_ignore()),
read_vcsignore: !(opts.no_ignore || opts.rg_alias_ignore() || opts.no_ignore_vcs),
require_git_to_read_vcsignore: !opts.no_require_git,
read_parent_ignore: !opts.no_ignore_parent,
read_global_ignore: !(opts.no_ignore
    || opts.rg_alias_ignore()
    || opts.no_global_ignore_file),

How the walker is configured

WorkerState::build_walker translates the Config flags into WalkBuilder calls:

builder
    .hidden(config.ignore_hidden)
    .ignore(config.read_fdignore)
    .parents(config.read_parent_ignore && (config.read_fdignore || config.read_vcsignore))
    .git_ignore(config.read_vcsignore)
    .git_global(config.read_vcsignore)
    .git_exclude(config.read_vcsignore)
    .require_git(config.require_git_to_read_vcsignore)
    .overrides(overrides)
    ...

if config.read_fdignore {
    builder.add_custom_ignore_filename(".fdignore");
}

if config.read_global_ignore
    && let Ok(basedirs) = etcetera::choose_base_strategy()
{
    let global_ignore_file = basedirs.config_dir().join("fd").join("ignore");
    if global_ignore_file.is_file() {
        let result = builder.add_ignore(global_ignore_file);
        ...
    }
}

for ignore_file in &config.ignore_files {
    let result = builder.add_ignore(ignore_file);
    ...
}

If a user-provided ignore file has parse errors, ignore::Error::Partial(_) is silently tolerated (the file is still applied) but other errors are surfaced via print_error.

Parent vs. local handling

By default, WalkBuilder::parents(true) makes the ignore crate walk upwards from each search root looking for .gitignore/.ignore/.fdignore files in ancestor directories. fd disables that traversal when read_parent_ignore is false. The combined check (config.read_fdignore || config.read_vcsignore) means parent traversal also turns off when the user disabled both ignore mechanisms entirely.

Hidden files vs. ignore files

These are independent. Hidden-file filtering is purely name-based (.foo is hidden) and applies regardless of any ignore file. Some quirks worth knowing:

  • By default, neither hidden files nor ignored files appear.
  • -H shows hidden files but still respects ignore rules.
  • -I shows ignored files but still hides dotfiles.
  • -HI (or -uu) shows everything.
  • The original 9.0.0 behaviour of automatically ignoring .git whenever -H was passed was reverted in 10.0.0 (see lore).

Diagnostic for "no results"

When the user types a pattern like ^\.gitignore, fd notices that the pattern only matches dotfiles but --hidden was not set, and emits a hint:

[fd error]: The pattern(s) seems to only match files with a leading dot, but
hidden files are filtered by default. Consider adding -H/--hidden to search
hidden files as well or adjust your search pattern(s).

This is implemented by pattern_matches_strings_with_leading_dot in src/regex_helper.rs and ensure_use_hidden_option_for_leading_dot_pattern in src/main.rs.

Entry points for modification

  • Add a new ignore source. Plug it into WorkerState::build_walker via add_custom_ignore_filename or add_ignore. The ignore crate handles all the matching logic — fd just decides which files to feed in.
  • Change the precedence of an existing source. Move the corresponding add_ignore / add_custom_ignore_filename call earlier or later in build_walker. The ignore crate evaluates files in registration order.
  • Change the global-ignore-file location. Edit the etcetera::choose_base_strategy().config_dir().join("fd").join("ignore") expression.
  • Walker — owns build_walker and the closure that runs the resulting walk.
  • Filters — the post-traversal predicates that complement ignore rules.
  • CLI parsing — the source of all the --no-… overrides described above.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Ignore rules – fd wiki | Factory