fd Fast Find

fd cheatsheet — fast file search with smart defaults. fd pattern, fd -e py, fd -t f, fd --hidden, fd -x cmd {}. Respects .gitignore. The find replacement.

6 min read

fd - Fast Find Cheatsheet

What it is

fd is a simple, fast, and user-friendly alternative to find for searching files and directories. It’s designed to be intuitive with sensible defaults.

Installation

Linux

Using your distribution’s package manager:

# Debian/Ubuntu
sudo apt update && sudo apt install fd-find

# Fedora
sudo dnf install fd-find

# Arch Linux
sudo pacman -S fd

If fdfind is installed instead of fd, you might need to create a symbolic link:

ln -s $(which fdfind) ~/.local/bin/fd

macOS

Using Homebrew:

brew install fd

Windows

Using Chocolatey:

choco install fd-find

Or using Scoop:

scoop install fd

Core Concepts

fd’s primary concept is its search pattern. By default, it treats your input as a "smart case" regex that matches anywhere in the path.

  • Smart Case: By default, fd is case-insensitive unless your pattern contains an uppercase letter.
  • Regex by Default: fd interprets your search pattern as a regular expression.
  • Ignores Hidden Files and .gitignore: By default, fd skips hidden files/directories and those ignored by .gitignore, .ignore, and .fdignore files.

Commands / Usage

Basic Searching

Find all files named main.rs in the current directory and subdirectories:

fd main.rs

Finds files whose name contains main.rs.

Find all files with the .js extension:

fd .js

Finds files ending with .js.

Find all directories named src:

fd --type d src

Finds directories named src.

Find all files, not directories:

fd --type f

Finds only files.

Find all symbolic links:

fd --type l

Finds only symbolic links.

Find files with specific extensions:

fd --extension rs --extension toml

Finds files ending in .rs OR .toml.

Find files that are NOT .md files:

fd --type f --no-ignore --glob '!*.md'

Finds files, ignoring the .gitignore rules, that do not end in .md.

Searching in Specific Directories

Search for config.yaml within the /etc directory:

fd config.yaml /etc

Searches for files named config.yaml starting from the /etc directory.

Search for Dockerfile in your home directory:

fd Dockerfile ~

Searches for files named Dockerfile starting from your home directory.

Controlling Case Sensitivity

Force case-insensitive search for README:

fd --case-sensitive README

This will not find readme.md.

Force case-sensitive search for README:

fd --case-sensitive README

This will find README.md.

Controlling Hidden Files and Ignores

Include hidden files and directories in the search:

fd --hidden .env

Searches for .env files, including hidden ones.

Show all files, even those ignored by .gitignore:

fd --no-ignore logfile.txt

Searches for logfile.txt, ignoring .gitignore and other ignore files.

Search only in the current directory (no recursion):

fd --max-depth 1 main.c

Searches for main.c only in the current directory.

Search up to 2 levels deep:

fd --max-depth 2 important_script.sh

Searches for important_script.sh up to two directories deep.

Using Regular Expressions

Find files starting with data- followed by digits:

fd '^data-\d+'

Matches files like data-123.csv or data-45.json.

Find files containing test followed by .py or .js:

fd 'test.*(py|js)'

Matches files like test_utils.py or my_test.js.

Executing Commands on Found Files

Delete all .bak files:

fd --delete --exec rm {} \;

Finds all .bak files and prompts for confirmation before deleting them.

List details of all .log files:

fd --exec ls -lh {} \;

Finds all .log files and runs ls -lh on each.

Move all .jpg files to an images directory:

fd --exec mv {} images/

Finds all .jpg files and moves them into the images directory.

Execute a custom script on found files:

fd --exec ./my_script.sh {} -- {}

Runs ./my_script.sh for each found file, passing the filename as an argument. The -- {} is important to separate fd arguments from script arguments if the script itself uses {}.

Execute commands in parallel:

fd --threads 4 --exec gzip {} \;

Finds files and compresses them using gzip in parallel using 4 threads.

Controlling Output

Print full paths (default):

fd .

Print relative paths:

fd --print0 | xargs -0 -I {} echo "Found: {}"

This example shows how to get relative paths and process them, though fd usually prints relative paths by default.

Search and print results as null-separated strings (useful for piping):

fd --print0 my_file.txt

Prints my_file.txt\0 if found.

Search for README but exclude the node_modules directory:

fd README --exclude node_modules

Finds README files, skipping any directory named node_modules.

Search for *.config.js but exclude files in .git directory:

fd --glob '*.config.js' --exclude '.git'

Finds JavaScript configuration files, ignoring anything within .git.

Search for files containing error but only in .log files:

fd --glob '*.log' error

Searches for the pattern error only within files matching the .log glob.

Common Patterns

Find all .py files and count them:

fd .py | wc -l

Counts the number of Python files.

Find all .js files and pipe them to grep:

fd .js | grep React

Finds .js files and then searches for lines containing "React" within those files.

Find all .txt files and print their sizes:

fd .txt --exec du -sh {} \;

Displays the human-readable size of each .txt file.

Find all files modified in the last 24 hours:

fd --changed-within 1d

Finds files modified within the last day.

Find all files larger than 1MB:

fd --size +1M

Finds files larger than 1 megabyte.

Find all files smaller than 1KB:

fd --size -1K

Finds files smaller than 1 kilobyte.

Find files changed more recently than a specific file:

fd --changed-after reference_file.txt

Finds files modified after reference_file.txt was last modified.

Find files not matching a pattern (using grep -v):

fd --print0 | xargs -0 grep -v 'TODO'

This is a common pattern to find files not containing "TODO". fd itself doesn’t have a direct "not matching" flag for content, so piping to grep -v is the way.

Find files and execute a command, handling spaces in filenames:

fd --print0 --exec my_command {} \; | xargs -0 -I {} echo "Processed: {}"

Safely handles filenames with spaces or special characters when piping to xargs.

Gotchas

  • Regex by Default: If you’re searching for a literal string that contains special regex characters (like ., *, +, ?, (, ), [ , ], {, }, |, ^, $), you might need to escape them or use --glob for simpler pattern matching. For example, to find a file literally named my.file, use fd 'my\.file' or fd --glob 'my.file'.
  • --exec and \; vs +: The --exec flag with \; executes the command once for each found file. Using + (e.g., fd --exec rm {} +) executes the command with multiple found files as arguments, similar to xargs. This is more efficient but might not be supported by all commands.
  • Default Ignores: Remember that hidden files and .gitignore entries are ignored by default. Use --hidden and --no-ignore to override this behavior.
  • fd vs fdfind: On some Linux distributions, the executable might be named fdfind due to a naming conflict. If fd doesn’t work, try fdfind. You can create a symlink to make fd work consistently.
  • Smart Case Sensitivity: If you want a truly case-insensitive search for a pattern like README, ensure your pattern doesn’t contain any uppercase letters. If you want a truly case-sensitive search, use --case-sensitive.