$linuxjunkies
>

How to Use fd Instead of find

Learn to use fd, the modern find alternative: friendlier syntax, smart defaults, .gitignore support, and parallel command execution with --exec.

BeginnerUbuntuDebianFedoraArch7 min readUpdated June 7, 2026

Before you start

  • A terminal and a user account with sudo privileges
  • Basic familiarity with navigating the filesystem from the command line
  • Internet or repository access to install packages

fd is a fast, user-friendly alternative to find. It offers sensible defaults — case-insensitive matching, automatic .gitignore respect, colored output, and a cleaner syntax — without sacrificing power. If you regularly reach for find and mentally rehearse its argument order each time, fd is worth fifteen minutes of your life.

Installing fd

The binary is called fd on most systems. On Debian and Ubuntu it was historically packaged as fd-find (with the binary named fdfind) to avoid a conflict with an older package; that conflict is largely resolved on modern releases but the package name persists.

Debian / Ubuntu

sudo apt install fd-find
# Symlink so you can type 'fd'
ln -s $(which fdfind) ~/.local/bin/fd

Fedora / RHEL 9+ / Rocky

sudo dnf install fd-find

The binary is fd directly on this family.

Arch Linux

sudo pacman -S fd

Verify the install

fd --version

You should see something like fd 9.x.x. Output will vary.

Basic Pattern Matching

fd takes a search pattern as a regular expression and an optional directory. Without a directory it searches the current working tree.

# Find any file whose name contains 'config'
fd config

# Search only inside /etc
fd config /etc

By default the match is case-insensitive. Use --case-sensitive (-s) when you need exact casing, or --ignore-case (-i) to be explicit. Contrast this with find, which is always case-sensitive unless you use -iname.

# Case-sensitive: matches 'Config' but not 'config'
fd -s Config /etc

Filtering by Type

The -t flag restricts results to a specific entry type. The most useful values are f (file), d (directory), l (symlink), and x (executable).

# Only directories whose name contains 'log'
fd -t d log

# Only executable files named 'python*'
fd -t x python /usr

Filtering by Extension

Use -e instead of crafting a regex like \.rs$. You can stack multiple -e flags.

# All Markdown files
fd -e md

# All C source and header files
fd -e c -e h ~/projects

Hidden Files and .gitignore

fd automatically skips hidden files (dot-files) and anything matched by .gitignore, .fdignore, or .ignore files. This is the right default for most development workflows. Override it when you need to dig deeper.

# Include hidden files
fd -H .bashrc ~

# Include files ignored by .gitignore
fd -I target ~/projects

# Include both hidden AND ignored files
fd -HI node_modules ~/projects

If you maintain a project and want fd to always skip a certain directory, add it to a .fdignore file in that directory — same syntax as .gitignore.

Limiting Search Depth

Deep trees can produce overwhelming output. --max-depth (-d) caps recursion.

# Only look one level deep
fd -d 1 -t d

# Two levels max, looking for YAML files
fd -d 2 -e yaml ~/infrastructure

Executing Commands with --exec and --exec-batch

This is where fd pulls ahead of a simple grep wrapper. --exec (-x) runs a command for each match in parallel; --exec-batch (-X) passes all matches as arguments to a single command invocation.

The placeholder {} expands to the full path. Additional placeholders:

  • {/} — filename only (basename)
  • {.} — path without extension
  • {//} — parent directory
  • {/.} — basename without extension

Per-file parallel execution

# Convert every PNG to WebP in parallel
fd -e png -x cwebp {} -o {.}.webp

# Show file sizes for all log files
fd -e log -x du -sh {}

Batch execution (single command, all matches)

# Open all TODO files in vim at once
fd TODO -X vim

# Count total lines across all Python files
fd -e py -X wc -l

Note: -x is parallel and non-deterministic in order; -X collects all results first. Use -X when order or a single process matters, -x when you want speed.

Comparing fd to find: Common Translations

find commandfd equivalent
find . -name "*.rs"fd -e rs
find . -type d -name "build"fd -t d build
find . -maxdepth 2 -name "*.yml"fd -d 2 -e yml
find . -name "*.log" -exec rm {} \;fd -e log -x rm {}
find /etc -iname "*nginx*"fd nginx /etc

Useful Real-World Patterns

Delete all compiled Python bytecode

fd -e pyc -x rm {}

Find files modified in the last 2 days

fd --changed-within 2d

Find large files (requires filtering with xargs or awk)

fd -t f -x du -sh {} | sort -rh | head -20

Search excluding a specific directory

fd -e js --exclude node_modules

Verifying Your Results

When you're unsure whether fd is skipping something it shouldn't, add --show-errors and temporarily override ignore rules with -HI to see the full picture, then narrow back down.

fd -HI --show-errors config /etc 2>&1 | head -40

If you want to confirm fd and find agree on a result set:

diff <(fd -HI -e conf /etc | sort) <(find /etc -name '*.conf' | sort)

Troubleshooting

Command not found after install on Debian/Ubuntu

The package installs the binary as fdfind. Either use that name, or create the symlink shown in the install section. Confirm with which fdfind.

Expected files are missing from results

Run with -HI to disable all filtering. If the file appears now, it's being hidden either because it's a dotfile (-H fixes that) or it matches an ignore file (-I fixes that). Check for a .gitignore or .fdignore in a parent directory.

Regex pattern not matching what you expect

fd uses Rust regex syntax. Character classes and anchors work as expected, but it matches against the filename only (not the full path) unless you pass --full-path (-p).

# Match against the full path, not just the filename
fd -p 'projects/web.*\.js$'

Performance seems slower than expected

fd is multithreaded by default. On spinning disks or network filesystems it can sometimes be slower than on NVMe due to seek overhead from parallel access. Try --threads 1 in those environments.

fd --threads 1 -e log /mnt/nfs
tested on:Ubuntu 24.04Fedora 40Arch rollingDebian 12

Frequently asked questions

Does fd replace find entirely?
For most day-to-day searches, yes. However, find has capabilities fd lacks, such as -perm permission filtering, -newer comparisons, and complex boolean logic with -and/-or/-not. For scripting in environments where fd may not be installed, find remains the portable choice.
Why does fd skip files I know exist?
fd respects .gitignore, .fdignore, and .ignore files, and hides dotfiles by default. Run with -HI to disable all filtering and confirm the file is reachable, then identify which rule is excluding it.
Is -x (--exec) safe to use with destructive commands like rm?
Be careful: -x runs commands in parallel without confirmation. Do a dry run first by replacing rm with echo to preview what would be deleted, then re-run with the real command.
Can fd search file contents like grep?
No. fd matches file and directory names only. For content searching, pipe fd results into ripgrep: fd -e py -x rg 'TODO' {} is one pattern, though rg alone with its own file filtering is usually simpler.
How does fd handle symbolic links?
By default fd does not follow symbolic links during traversal. Pass --follow (-L) to make fd follow symlinks, but be aware this can produce duplicate results or infinite loops in circular link structures.

Related guides