# fd excludes hidden and ignored files before you type a flag, and the crate ships as fd-find

> fd is a Rust rewrite of the find habit, with regular expressions by default, smart case, parallel traversal and .gitignore-aware filtering that runs before you ask for it. The binary is called fd while the crate is fd-find, the source floor is Rust 1.90.0 on edition 2024, and the two command execution flags behave very differently.

**sharkdp/fd** — GitHub describes it as A simple, fast and user-friendly alternative to 'find'. The repository metadata lists Rust as its primary language. The metadata lists the Apache-2.0 license. This article stays within the project description and details documented in the GitHub repository README.

- Repository: https://github.com/sharkdp/fd
- Stars: 44,590 · Forks: 1,147
- Language: Rust
- License: Apache-2.0
- Published: 2026-08-13 · Updated: 2026-08-18 · Language: en
- Canonical page: https://hysenlabs.com/projects/sharkdp-fd

## fd PATTERN instead of find -iname '*PATTERN*'

The whole argument convention is one line: fd PATTERN where find would need find -iname '*PATTERN*'. With one argument, fd searches the current directory recursively for entries that contain the pattern, which is substring matching rather than an anchored name:

```bash
> fd netfl
Software/python/imdb-ratings/netflix-details.py
```

The pattern is a regular expression by default, and the README's example anchors both ends, searching /etc for entries starting with x and ending with rc:

```bash
> cd /etc
> fd '^x.*rc$'
X11/xinit/xinitrc
X11/xinit/xserverrc
```

That default has consequences when a script moves across from find. A name containing a dot, a bracket or a plus is regex syntax here, not a literal, and there is no implicit quoting. A second positional argument is the root directory, so fd passwd /etc searches that tree instead of the working directory. Called with no arguments at all, fd lists every entry recursively, similar to ls -R, and to list everything inside a named directory you need a catch-all pattern such as . or ^. Smart case is on: matching is case-insensitive unless your pattern contains an uppercase character.

## Hidden files and gitignored paths are filtered before you ask

This is the behaviour that surprises people porting shell scripts, and it is the default rather than a flag. Hidden directories and files are skipped, and in a directory that is a Git repository the patterns from .gitignore are honoured as well:

```bash
> fd pre-commit
> fd -H pre-commit
.git/hooks/pre-commit.sample
```

The same example also shows what happens with each flag. Without -H the pre-commit hook inside .git is invisible; with -H it appears. The -I option, spelled --no-ignore, does the same job for ignored paths, which is how a build artifact under target/debug becomes visible:

```bash
> fd num_cpu
> fd -I num_cpu
target/debug/deps/libnum_cpus-f5ce7ef99006aa05.rlib
```

To see everything, combine them as -HI or use -u, spelled --unrestricted. Matching is on the filename only by default, so a path component will not match unless you add --full-path or -p. The practical failure mode is a script that quietly returns nothing: a search for a compiled dependency name inside a Rust build tree comes back empty until -I is added, and nothing in the output distinguishes that from the file not existing. Filename-only matching has the same shape of surprise, and a pattern that walks directories needs -p before the README's .git/config glob example can match anything.

## The binary is fd, the crate is fd-find, and both completions ship

Cargo.toml names the package fd-find and version 10.5.0, while the binary it builds is something else:

```toml
[[bin]]
name = "fd"
path = "src/main.rs"
```

That gap is why the repository carries completion files under two names. The Makefile's completions target builds a bash and a fish completion from the binary itself, generates a PowerShell completion, and then copies four more from contrib/completion, named for both the fd and the fdfind spelling:

```makefile
completions: autocomplete/fd.bash autocomplete/fd.fish autocomplete/_fd.ps1 autocomplete/_fd autocomplete/_fdfind autocomplete/fdfind.bash autocomplete/fdfind.fish
```

The install target then places the executable and every one of those completions, bash into bash-completion, fish into vendor_completions.d, and the zsh ones into site-functions. The consequence for a user is that the name you type and the name on the registry are not the same string, so a script that installs the crate and then invokes fd has two separate things to get right. The archive name is versioned too, since the Makefile switches to fd-v$(VERSION) when VERSION is defined, and the release archives are built by a shell script under scripts/.

## Building from source needs Rust 1.90.0 and edition 2024

The build requirements are stated in the manifest rather than in prose, and they are not trivial ones:

```toml
edition= "2024"
rust-version = "1.90.0"
```

Two things follow for anyone compiling instead of installing a packaged binary. The language floor is 1.90.0, so an older pinned toolchain in a container image will refuse the crate rather than degrade. And edition 2024 changes how several language rules apply, which matters for a codebase that vendors the source. The dependency list explains what the program is made of: the ignore crate handles the .gitignore and hidden-file rules, regex and regex-syntax do pattern matching, globset backs the -g option, aho-corasick handles literal search, crossbeam-channel carries results out of the parallel traversal, and ctrlc handles interruption. The colour output comes from lscolors, declared with default features off and the nu-ansi-term feature enabled, which is why results are coloured by file type the way ls colours them.

## jemalloc is switched off on macOS, and the switch lives in main.rs

One dependency decision in Cargo.toml is a bug workaround with a tracking issue attached. jemalloc is disabled on macOS because of a jemalloc bug in combination with macOS Catalina, the comment points at issue 498, and it carries an instruction that matters if you patch anything: the state has to be kept in sync with src/main.rs, where the allocator for the program is set. In other words, the allocator is not only a build-time choice, it is chosen in code. The conditional is scoped to targets that are neither Windows, Android nor macOS, so the memory behaviour of the same binary is not identical everywhere. For most users this is invisible. For anyone benchmarking fd, reading a bug report about memory on one platform, or packaging for several systems, it is the first file to open, because a fix applied in only one of the two places produces a build that compiles and behaves differently from what the manifest claims.

## -x runs your command once per result, -X runs it once with all of them

The two execution flags are the ones to get right, because they differ in process count and in blast radius. -x, spelled --exec, runs the command for each result in parallel. -X, spelled --exec-batch, launches the command a single time with every result as an argument. Formatting sources in place is the -x shape:

```bash
fd -e h -e cpp -x clang-format -i
```

The README explains the ordering rule that comes with it: any positional arguments after -x belong to the command template rather than to fd, which is why -i for clang-format is passed after the flag and why a pattern or search path has to come before it, as in fd pattern path -x echo. Placeholders are also available, where {} stands for the result and {.} for the same path without its extension:

```bash
fd -e jpg -x convert {} {.}.png
```

Consequence for scripts: a mistyped pattern under -x is not a dry run. fd finds matching files, starts the command once per file in parallel, and something like clang-format -i rewrites all of them before you can intervene. The -l option, spelled --list-details, is the read-only counterpart, running ls on each result so you can see permissions, owners and sizes before committing to a destructive template.

## Conclusion

Reach for fd when you search a working tree and want ignored build output and dotfiles left out of the way, and when you want a pattern that is a real regular expression rather than a shell glob. Keep find for the cases fd says it does not aim at, which is everything requiring the full expression language. Verify three things before you port a script: that the crate name you install is fd-find while the binary is fd, that your Rust toolchain is 1.90.0 or newer on edition 2024 if you build from source, and that any command using -x writes in place, because the flag runs your template once per result in parallel with no confirmation.

## FAQ

### What is the fd command?

fd is a program written in Rust to find entries in your filesystem, positioned as a simple, fast and user-friendly alternative to find. The README is explicit that it does not aim to support all of find's functionality and instead offers opinionated defaults for the majority of use cases.

### Is fd faster than find?

The README attributes fd's speed to parallelized directory traversal and links a benchmark section for the numbers, which this page does not reproduce. It also states plainly that fd does not aim to support all of find's functionality, so the comparison is not like for like.

### How to install fd in Linux?

The README links an Installation section, and the crate is published on crates.io under the name fd-find, with the API documentation at docs.rs/fd-find. Building from source needs Rust 1.90.0 or newer, and the repository's Makefile has an install target that copies the fd binary and the bash, fish and zsh completions into place.

### Can fd find hidden files?

Yes, with -H or --hidden, which stops fd from skipping hidden directories and files, and .gitignore patterns are bypassed separately with -I or --no-ignore. Combining them as -HI, or using -u for unrestricted search, shows everything.

## Sources

- [Official README](https://github.com/sharkdp/fd#readme)
- [Project repository](https://github.com/sharkdp/fd)
- [Release notes](https://github.com/sharkdp/fd/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/sharkdp-fd
