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,
fdis case-insensitive unless your pattern contains an uppercase letter. - Regex by Default:
fdinterprets your search pattern as a regular expression. - Ignores Hidden Files and
.gitignore: By default,fdskips hidden files/directories and those ignored by.gitignore,.ignore, and.fdignorefiles.
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.
Fine-tuning Search
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--globfor simpler pattern matching. For example, to find a file literally namedmy.file, usefd 'my\.file'orfd --glob 'my.file'. --execand\;vs+: The--execflag 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 toxargs. This is more efficient but might not be supported by all commands.- Default Ignores: Remember that hidden files and
.gitignoreentries are ignored by default. Use--hiddenand--no-ignoreto override this behavior. fdvsfdfind: On some Linux distributions, the executable might be namedfdfinddue to a naming conflict. Iffddoesn’t work, tryfdfind. You can create a symlink to makefdwork 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.