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):
-E/--excludepatterns from the command line. Wired in viaOverrideBuilderinWorkerState::build_overrides(src/walk.rs)..gitignorein the current and ancestor directories, plus the global gitignore (~/.config/git/ignore) and.git/info/exclude. Honoured whenConfig::read_vcsignoreis true and either.git/is present or--no-require-gitwas passed..ignore(the ripgrep-style file) in the same locations, whenConfig::read_fdignoreis true..fdignorein the same locations, registered withWalkBuilder::add_custom_ignore_filename(".fdignore")whenConfig::read_fdignoreis true.- Global fdignore at
${etcetera::config_dir()}/fd/ignore(typically~/.config/fd/ignoreon Linux/macOS or%APPDATA%\fd\ignoreon Windows). Loaded byWalkBuilder::add_ignoreinWorkerState::build_walker. Disabled by--no-global-ignore-file. - Custom ignore files passed with
--ignore-file PATH. Loaded by the sameadd_ignorecall as the global file. - Hidden files (names starting with
.) are skipped whenConfig::ignore_hiddenis 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.
-Hshows hidden files but still respects ignore rules.-Ishows ignored files but still hides dotfiles.-HI(or-uu) shows everything.- The original 9.0.0 behaviour of automatically ignoring
.gitwhenever-Hwas 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_walkerviaadd_custom_ignore_filenameoradd_ignore. Theignorecrate 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_filenamecall earlier or later inbuild_walker. Theignorecrate evaluates files in registration order. - Change the global-ignore-file location. Edit the
etcetera::choose_base_strategy().config_dir().join("fd").join("ignore")expression.
Related pages
- Walker — owns
build_walkerand 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.