fd
is a program to find entries in your filesystem.
It is a simple, fast and user-friendly alternative to find
.
While it does not aim to support all of find
‘s powerful functionality, it provides sensible
(opinionated) defaults for a majority of use cases.
Installation • How to use • Troubleshooting
- Intuitive syntax:
fd PATTERN
instead offind -iname '*PATTERN*'
. - Regular expression (default) and glob-based patterns.
- Very fast due to parallelized directory traversal.
- Uses colors to highlight different file types (same as
ls
). - Supports parallel command execution
- Smart case: the search is case-insensitive by default. It switches to
case-sensitive if the pattern contains an uppercase
character*. - Ignores hidden directories and files, by default.
- Ignores patterns from your
.gitignore
, by default. - The command name is 50% shorter* than
find
:-).
First, to get an overview of all available command line options, you can either run
fd -h
for a concise help message or fd --help
for a more detailed
version.
fd is designed to find entries in your filesystem. The most basic search you can perform is to
run fd with a single argument: the search pattern. For example, assume that you want to find an
old script of yours (the name included netflix
):
for any entries that contain the pattern
netfl
.
The search pattern is treated as a regular expression. Here, we search for entries that start
with x
and end with rc
:
fd
is documented here.
If we want to search a specific directory, it can be given as a second argument to fd:
fd can be called with no arguments. This is very useful to get a quick overview of all entries
in the current directory, recursively (similar to ls -R
):
a catch-all pattern such as
.
or ^
:
Often, we are interested in all files of a particular type. This can be done with the -e
(or
--extension
) option. Here, we search for all Markdown files in the fd repository:
-e
option can be used in combination with a search pattern:
To find files with exactly the provided search pattern, use the -g
(or --glob
) option:
search results. To disable this behavior, we can use the
-H
(or --hidden
) option:
search folders (and does not show files) that match one of the
.gitignore
patterns. To disablethis behavior, we can use the
-I
(or --no-ignore
) option:
everything (
-HI
) or use -u
/--unrestricted
.
By default, fd only matches the filename of each file. However, using the --full-path
or -p
option,
you can match against the full path.
fd
provides two ways to execute external commands for each of your search results:
- The
-x
/--exec
option runs an external command for each of the search results (in parallel). - The
-X
/--exec-batch
option launches the external command once, with all search results as arguments.
Recursively find all zip archives and unpack them:
If there are two such files, file1.zip
and backup/file2.zip
, this would execute
unzip file1.zip
and unzip backup/file2.zip
. The two unzip
processes run in parallel
(if the files are found fast enough).
Find all *.h
and *.cpp
files and auto-format them inplace with clang-format -i
:
fd -e h -e cpp -x clang-format -i
Note how the -i
option to clang-format
can be passed as a separate argument. This is why
we put the -x
option last.
Find all test_*.py
files and open them in your favorite editor:
Note that we use capital -X
here to open a single vim
instance. If there are two such files,
test_basic.py
and lib/test_advanced.py
, this will run vim test_basic.py lib/test_advanced.py
.
To see details like file permissions, owners, file sizes etc., you can tell fd
to show them
by running ls
for each result:
fd … -X ls -lhd --color=always
This pattern is so useful that fd
provides a shortcut. You can use the -l
/--list-details
option to execute ls
in this way: fd … -l
.
The -X
option is also useful when combining fd
with ripgrep (rg
) in order to search within a certain class of files, like all C++ source files:
fd -e cpp -e cxx -e h -e hpp -X rg 'std::cout'
Convert all *.jpg
files to *.png
files:
fd -e jpg -x convert {} {.}.png
Here, {}
is a placeholder for the search result. {.}
is the same, without the file extension.
See below for more details on the placeholder syntax.
The terminal output of commands run from parallel threads using -x
will not be interlaced or garbled,
so fd -x
can be used to rudimentarily parallelize a task run over many files.
An example of this is calculating the checksum of each individual file within a directory.
-x
and -X
options take a command template as a series of arguments (instead of a single string).If you want to add additional options to
fd
after the command template, you can terminate it with a ;
.
The syntax for generating commands is similar to that of GNU Parallel:
{}
: A placeholder token that will be replaced with the path of the search result
(documents/images/party.jpg
).{.}
: Like{}
, but without the file extension (documents/images/party
).{/}
: A placeholder that will be replaced by the basename of the search result (party.jpg
).{//}
: The parent of the discovered path (documents/images
).{/.}
: The basename, with the extension removed (party
).
If you do not include a placeholder, fd automatically adds a {}
at the end.
For -x
/--exec
, you can control the number of parallel jobs by using the -j
/--threads
option.
Use --threads=1
for serial execution.
Sometimes we want to ignore search results from a specific subdirectory. For example, we might
want to search all hidden files and directories (-H
) but exclude all matches from .git
directories. We can use the -E
(or --exclude
) option for this. It takes an arbitrary glob
pattern as an argument:
We can also use this to skip mounted directories:
To make exclude-patterns like these permanent, you can create a .fdignore
file. They work like
.gitignore
files, but are specific to fd
. For example:
Note
fd
also supports .ignore
files that are used by other programs such as rg
or ag
.
If you want fd
to ignore these patterns globally, you can put them in fd
‘s global ignore file.
This is usually located in ~/.config/fd/ignore
in macOS or Linux, and %APPDATA%fdignore
in
Windows.
You may wish to include .git/
in your fd/ignore
file so that .git
directories, and their contents
are not included in output if you use the --hidden
option.
You can use fd
to remove all files and directories that are matched by your search pattern.
If you only want to remove files, you can use the --exec-batch
/-X
option to call rm
. For
example, to recursively remove all .DS_Store
files, run:
fd
without -X rm
first. Alternatively, use rm
s “interactive”option:
have to use
rm
s --recursive
/-r
flag to remove directories.
Note
There are scenarios where using fd … -X rm -r
can cause race conditions: if you have a
path like …/foo/bar/foo/…
and want to remove all directories named foo
, you can end up in a
situation where the outer foo
directory is removed first, leading to (harmless) “‘foo/bar/foo’:
No such file or directory” errors in the rm
call.
This is the output of fd -h
. To see the full set of command-line options, use fd --help
which
also includes a much more detailed help text.


Sign Up to Our Newsletter
Be the first to know the latest updates
Whoops, you're not connected to Mailchimp. You need to enter a valid Mailchimp API key.
19 Comments
snide
Big sharkdp fan. Ty you for making awesome software that i use DAILY.
bat, fd, hexyl, hyperfine
I'm going to take this moment to remind all of you well-paid engineers that if we each spread $10 a month sponsoring talented software makers like sharkdp the Internet would be a better place.
So many great little tools out there and we should try to support an ecosystem for them.
oguz-ismail
Every fucking time
tucnak
kstrauser
I use the heck out of fd daily and it’s in my standard installation on new machines. I’ve used find for years and it’s great in its own ways, but convenient ergonomics isn’t among them.
I’m 100% on board with this recent-ish trend toward new replacement utilities that may or may not retain all of the flexibility of the originals but are vastly easier to use for common cases.
agumonkey
As much as i love new rust cli tools, `fd` ended up in the same bag as tar and ln.. I can never retain how to use it. I don't blame anybody .. I'm just witness that I always have to re-read the man from scratch to get anything done. And I'm not a gnu find lover.. with all its idiosyncracies.. somehow it registers better.
grenran
annoyingly fd also stands for file descriptor
travisgriggs
I’ll have to try this out. I admit that most of my uses of find looke like
find . | grep what_i_am_looking_for
Because I can never remember how finds arguments work. I like the integrated xargs like behavior as well.
One thing I did not see in there was how fd handles symlink directory traversal? Searched the whole readme for it, and only found options to match on symlinks or not.
meisel
Personally I prefer bfs (https://github.com/tavianator/bfs) because it does a breadth-first search
actinium226
Is anyone else bothered by the fact that by default it ignores a lot of folders? I use `find` when I'm like 'I just want to know where on my system this is, wherever it might be'
I know fd has options to not ignore things, but I can never remember them, so I just go back to find because I know it'll search everything.
sandos
Yeah, I was trying the -exec functionality of find just yesterday, something which Iv'e done many times before, but that was long ago.
I eventually gave up! Thats how ergonomic find is :)
rednafi
One reason I haven’t picked up any of these newfangled Rust tools like bat, exa, or fd is that I can barely remember the options for the originals.
For me, anything that isn’t a drop-in replacement for the OG tools isn’t worth the friction. I use ripgrep inside VS Code but vanilla grep on the command line because of years of muscle memory.
That said, I don’t care what language a tool is written in as long as it works. One of my favorite Unix tools is GNU Stow, and it’s written in Perl. Even if these Rust tools were drop-in replacements, I probably wouldn’t bother installing them manually. As a user, the speed improvements and memory safety don’t really matter to me.
There are other languages, like Go, where memory safety is guaranteed as well, and Go’s performance is more than adequate for tooling—with the added benefit of getting more engagement from the community. So I’m not entirely convinced by this “Rust is the savior” narrative.
That said, if macOS or Ubuntu decided to hot-swap the OG tools with Rust alternatives that behave exactly like their predecessors, I probably wouldn’t complain—as long as it doesn’t disrupt my workflow.
Babkock
One of those essential tools, that's not ever included with GNU/Linux by default, but I always install almost immediately along with ripgrep, bat, fzf, htop.
HeadlessChild
This saved me a ton of time when I had to migrate id ownership of files in ancient NFS shares.
[0] https://news.ycombinator.com/item?id=31489004
alkh
Imo, everyone should check https://terminaltrove.com/ from time to time. There, I have found easy replacements to commonly used tools:
find -> fd, time(for runtime comparison) -> hyperfine, grep->ripgrep, asciinema + converting to .gif -> t-rec[1], manually creating convertional commits -> koji[2], etc.
[1]https://terminaltrove.com/t-rec/
[2]https://terminaltrove.com/koji/
enricozb
I wish fd and rg would align some of their flags. For example, both fd and rg have a –type, but for fd it means file/directory/symlink etc. For rg it means the file MIME type. Another example is that fd has an –extension flag, and rg doesn't.
Since I believe the correlation of usage of these tools is high, I think they could benefit from having similarly named flags.
puffybuf
fzf, ripgrep are some command line tools I like. Check them out. Being able to quickly search your history with fuzzy finder is so useful.
usrbinbash
There are many completely unnecessary "reworks" of classic UNIX stdutils that add very little to no value, and instead pitch themselves purely on "written in {lang-the-dev-likes}" or being "blazing fast" or something similar.
`fd` isn't one of those.
`fd` is amazing.
It is simpler, faster and easier to grok than `find`, the commands syntax is a straight up improvement, it comes with sane defaults which makes the easy things and common usecases simple, while the harder ones are way more accessible. It uses colored output in an actually useful way, its manpage is more structured and easier to read…
and MOST IMPORTANTLY
…it is capable of running commands on search results with parallel execution out of the box, so no need to get GNU parallel into the command.
THIS is the kind of renewal of classic command line utilitis we need!
Literally the only pain point for me, is that it doesn't use glob-patterns by default, and that is easily fixed by a handy
pimlottc
For folks on macOS, you can also use "mdfind" as a command-line interface for macOS Spotlight search
https://ss64.com/mac/mdfind.html
BeetleB
I never managed to use find. I would always find a different way to solve my problem (e.g. Midnight Commander).
I use fd all the time.
Simply having a better command line interface is a big deal.