关于 fd
用于快速查找文件和目录的现代化替代品。语法简洁直观,支持正则表达式和文件类型过滤,与 shell 工具完全兼容。
主要功能
- 01按名称快速搜索文件和目录
- 02通过文件扩展名进行精准过滤
- 03支持正则表达式和模式匹配
- 04与管道和其他命令行工具无缝集成
适用场景
- 01在大型代码库中快速定位特定文件类型
- 02构建复杂的文件搜索工作流
- 03提升命令行脚本的性能
安装
选择你的系统或包管理器,复制命令到终端运行。
安装完成后运行fd --version确认安装成功。
命令示例
常用命令按使用顺序排列。
详细介绍
fd
fd 是一款用于查找文件系统条目的程序。
它是 find 的简单、快速且易用的替代品。
虽然它并不打算支持 find 的所有强大功能,但它为大多数使用场景提供了合理的
(带有主观取舍的)默认设置。
功能
- 语法直观:使用
fd PATTERN,而不是find -iname '*PATTERN*'。 - 支持正则表达式(默认)和基于 glob 的模式。
- 由于并行遍历目录,速度非常快。
- 使用颜色突出显示不同的文件类型(与
ls相同)。 - 支持并行执行命令
- 智能大小写:默认情况下搜索不区分大小写。如果模式中包含大写 字符,则切换为区分大小写*。
- 默认忽略隐藏目录和文件。
- 默认忽略
.gitignore中的模式。 - 命令名称比
find短 50%* :-).
演示
使用方法
首先,如需概览所有可用的命令行选项,可以运行
fd -h 查看简明帮助信息,或运行 fd --help 查看更详细的
版本。
简单搜索
fd 专为查找文件系统中的条目而设计。最基本的搜索方式是使用单个参数运行 fd:搜索模式。例如,假设你想找到自己以前写的一个脚本(名称中包含 netflix):
> fd netfl
Software/python/imdb-ratings/netflix-details.py
像这样只提供一个参数时,fd 会递归搜索当前目录,查找任何包含模式 netfl 的条目。
正则表达式搜索
搜索模式会被视为正则表达式。下面我们搜索以 x 开头、以 rc 结尾的条目:
> cd /etc
> fd '^x.*rc$'
X11/xinit/xinitrc
X11/xinit/xserverrc
fd 使用的正则表达式语法在此处有文档说明。
指定根目录
如果要搜索特定目录,可以将其作为第二个参数传给 fd:
> fd passwd /etc
/etc/default/passwd
/etc/pam.d/passwd
/etc/passwd
递归列出所有文件
调用 fd 时可以不带参数。这对于快速概览当前目录中的所有条目(递归列出,类似于 ls -R)非常有用:
> cd fd/tests
> fd
testenv
testenv/mod.rs
tests.rs
如果要使用此功能列出指定目录中的所有文件,则必须使用 . 或 ^ 这样的匹配所有内容的模式:
> fd . fd/tests/
testenv
testenv/mod.rs
tests.rs
搜索特定文件扩展名
我们经常需要查找某种类型的所有文件。可以使用 -e(或
--extension)选项来完成。下面我们搜索 fd 仓库中的所有 Markdown 文件:
> cd fd
> fd -e md
CONTRIBUTING.md
README.md
-e 选项可以与搜索模式组合使用:
> fd -e rs mod
src/fshelper/mod.rs
src/lscolors/mod.rs
tests/testenv/mod.rs
搜索特定文件名
如需查找名称与给定搜索模式完全一致的文件,请使用 -g(或 --glob)选项:
> fd -g libc.so /usr
/usr/lib32/libc.so
/usr/lib/libc.so
隐藏和忽略的文件
默认情况下,fd 不会搜索隐藏目录,也不会在搜索结果中显示隐藏文件。要禁用此行为,可以使用 -H(或 --hidden)选项:
> fd pre-commit
> fd -H pre-commit
.git/hooks/pre-commit.sample
如果我们在 Git 仓库(或包含 Git 仓库的目录)中工作,fd 不会搜索匹配某个 .gitignore 模式的文件夹(也不会显示其中的文件)。要禁用此行为,可以使用 -I(或 --no-ignore)选项:
> fd num_cpu
> fd -I num_cpu
target/debug/deps/libnum_cpus-f5ce7ef99006aa05.rlib
要真正搜索所有文件和目录,只需组合隐藏和忽略选项以显示所有内容(-HI),或使用 -u/--unrestricted。
匹配完整路径
默认情况下,fd 只匹配每个文件的文件名。不过,使用 --full-path 或 -p 选项,
即可匹配完整路径。
> fd -u -p -g '**/.git/config'
> fd -p '.*/lesson-\d+/[a-z]+.(jpg|png)'
命令执行
除了显示搜索结果,你通常还会想对这些结果执行一些操作。fd
提供了两种方式,可针对每个搜索结果执行外部命令:
-x/--exec选项会针对每个搜索结果运行一次外部命令(并行执行)。-X/--exec-batch选项会启动一次外部命令,并将所有搜索结果作为参数传入。
示例
递归查找所有 zip 压缩包并解压:
fd -e zip -x unzip
如果有两个这样的文件,分别是 file1.zip 和 backup/file2.zip,那么会执行
unzip file1.zip 和 unzip backup/file2.zip。两个 unzip 进程会并行运行
(如果能足够快地找到这些文件)。
查找所有 *.h 和 *.cpp 文件,并使用 clang-format -i 自动就地格式化:
fd -e h -e cpp -x clang-format -i
请注意,clang-format 的 -i 选项可以作为单独的参数传入。因此我们将
-x 选项放在最后。
-x 后的所有位置参数都属于命令模板,而非 fd 本身。如果还要传入模式或搜索路径,
请将 -x 放在最后:
fd pattern path -x echo
查找所有 test_*.py 文件,并在你喜欢的编辑器中打开:
fd -g 'test_*.py' -X vim
请注意,这里使用大写的 -X 来打开单个 vim 实例。如果有两个这样的文件,
test_basic.py 和 lib/test_advanced.py,则会运行 vim test_basic.py lib/test_advanced.py。
如要查看文件权限、所有者、文件大小等详细信息,可以让 fd 为每个搜索结果运行
ls 来显示这些信息:
fd … -X ls -lhd --color=always
这种模式非常实用,因此 fd 提供了快捷方式。可以使用 -l/--list-details
选项以这种方式执行 ls:fd … -l。
将 fd 与 ripgrep(rg)结合使用时,-X
选项也很有用,可用于在特定类别的文件中搜索,例如所有 C++ 源文件:
fd -e cpp -e cxx -e h -e hpp -X rg 'std::cout'
将所有 *.jpg 文件转换为 *.png 文件:
fd -e jpg -x convert {} {.}.png
这里,{} 是搜索结果的占位符。{.} 的含义相同,但不包含文件扩展名。
占位符语法的更多详情见下文。
使用 -x 在并行线程中运行命令时,终端输出不会交错或乱码,
因此可以用 fd -x 对涉及大量文件的任务进行简单的并行处理。
例如,可以计算目录中每个文件的校验和。
fd -tf -x md5sum > file_checksums.txt
占位符语法
-x 和 -X 选项接受由一系列参数构成的命令模板(而非单个字符串)。
如果想在命令模板后添加其他 fd 选项,可以用 \; 结束命令模板。
例如,fd -x echo \; pattern path 会将 pattern path 视为 fd 参数,而不是
传给 echo。实际使用时,通常写成 fd pattern path -x echo 会更清晰。
命令生成语法与 GNU Parallel 类似:
{}:占位符标记,会替换为搜索结果的路径 (documents/images/party.jpg)。{.}:与{}类似,但不包含文件扩展名(documents/images/party)。{/}:占位符,会替换为搜索结果的基本文件名(party.jpg)。{//}:已发现路径的父级路径(documents/images)。{/.}:不带扩展名的基本文件名(party)。
如果没有包含占位符,fd 会自动在末尾添加 {}。
并行执行与串行执行
对于 -x/--exec,可以使用 -j/--threads 选项控制并行任务数。
使用 --threads=1 可进行串行执行。
排除特定文件或目录
有时,我们希望忽略来自某个子目录的搜索结果。例如,我们可能希望搜索所有隐藏文件和目录(-H),但排除所有 .git
目录中的匹配项。可以使用 -E(或 --exclude)选项来实现。该选项接受任意 glob
模式作为参数:
> fd -H -E .git …
也可以用它来跳过已挂载的目录:
> fd -E /mnt/external-drive …
……或者跳过某些文件类型:
> fd -E '*.bak' …
若要永久使用此类排除模式,可以创建 .fdignore 文件。它们的作用类似于
.gitignore 文件,但专用于 fd。例如:
> cat ~/.fdignore
/mnt/external-drive
*.bak
说明
fd也支持其他程序(如rg或ag)使用的.ignore文件。
如果希望 fd 在全局范围内忽略这些模式,可以将它们放入 fd 的全局忽略文件中。
在 macOS 或 Linux 上,该文件通常位于 ~/.config/fd/ignore;在
Windows 上则位于 %APPDATA%\fd\ignore。
你可能需要将 .git/ 加入 fd/ignore 文件,这样使用 --hidden 选项时,.git 目录及其内容
就不会出现在输出中。
删除文件
可以使用 fd 删除所有与搜索模式匹配的文件和目录。
如果只想删除文件,可以使用 --exec-batch/-X 选项调用 rm。例如,要递归删除所有 .DS_Store 文件,请运行:
> fd -H '^\.DS_Store$' -tf -X rm
如果不确定,请务必先在不带 -X rm 的情况下调用 fd。或者,使用 rm 的“交互式”
选项:
> fd -H '^\.DS_Store$' -tf -X rm -i
如果还想删除某一类目录,也可以使用相同的方法。需要使用 rm 的 --recursive/-r 标志来删除目录。
说明
在某些情况下,使用
fd … -X rm -r可能会导致竞态条件:如果路径类似…/foo/bar/foo/…,而你想删除所有名为foo的目录,可能会先删除外层的foo目录,导致rm调用中出现(无害的)"'foo/bar/foo':No such file or directory" 错误。
命令行选项
以下是 fd -h 的输出。若要查看完整的命令行选项,请使用 fd --help,其中还包含更详细的帮助文本。
Usage: fd [OPTIONS] [pattern [path]...]
Arguments:
[pattern] the search pattern (a regular expression, unless '--glob' is used; optional)
[path]... the root directories for the filesystem search (optional)
Options:
-H, --hidden Search hidden files and directories
-I, --no-ignore Do not respect .(git|fd)ignore files
-s, --case-sensitive Case-sensitive search (default: smart case)
-i, --ignore-case Case-insensitive search (default: smart case)
-g, --glob Glob-based search (default: regular expression)
-a, --absolute-path Show absolute instead of relative paths
-l, --list-details Use a long listing format with file metadata
-L, --follow Follow symbolic links
-p, --full-path Search full abs. path (default: filename only)
-d, --max-depth <depth> Set maximum search depth (default: none)
-E, --exclude <glob> Exclude entries that match the given glob pattern
-t, --type <filetype> Filter by type: file (f), directory (d/dir), symlink (l),
executable (x), empty (e), socket (s), pipe (p), char-device
(c), block-device (b)
-e, --extension <ext> Filter by extension
-S, --size <size> Limit results based on the size of files
--changed-within <date|dur> Filter by file modification time (newer than)
--changed-before <date|dur> Filter by file modification time (older than)
-o, --owner <user:group> Filter by owning user and/or group
--format <fmt> Print results according to template
-x, --exec <cmd>... Execute a command for each search result
-X, --exec-batch <cmd>... Execute a command with all search results at once
-c, --color <when> When to use colors [default: auto] [possible values: auto,
always, never]
--hyperlink[=<when>] Add hyperlinks to output paths [default: never] [possible
values: auto, always, never]
--ignore-contain <name> Ignore directories containing the named entry
-h, --help Print help (see more with '--help')
-V, --version Print version
请注意,也可以在模式和/或路径之后给出选项。
基准测试
让我们在我的主目录中搜索文件名以 [0-9].jpg 结尾的文件。该目录包含约 750,000
个子目录和约 400 万个文件。为了计算平均值并进行统计分析,我使用了
hyperfine。以下基准测试均在磁盘缓存已预热/预填充的情况下进行(冷磁盘缓存下的结果趋势相同)。
先从 find 开始:
Benchmark 1: find ~ -iregex '.*[0-9]\.jpg$'
Time (mean ± σ): 19.922 s ± 0.109 s
Range (min … max): 19.765 s … 20.065 s
如果不需要执行正则表达式搜索,find 会快得多:
Benchmark 2: find ~ -iname '*[0-9].jpg'
Time (mean ± σ): 11.226 s ± 0.104 s
Range (min … max): 11.119 s … 11.466 s
现在用 fd 做相同的测试。请注意,fd 默认会执行正则表达式
搜索。这里需要使用 -u/--unrestricted 选项,才能进行公平比较。否则,fd 无需遍历隐藏文件夹和
被忽略的路径(见下文):
Benchmark 3: fd -u '[0-9]\.jpg$' ~
Time (mean ± σ): 854.8 ms ± 10.0 ms
Range (min … max): 839.2 ms … 868.9 ms
在这个特定示例中,fd 比 find -iregex 快约 23 倍,比 find -iname 快约 13 倍。顺便说一下,两个工具找到的都是完全相同的 546 个文件 :smile:。
注意:这只是某台机器上的一个特定基准测试。虽然我们进行了许多不同的测试(并得到了稳定一致的结果),但你的情况可能有所不同!我们鼓励大家亲自试用。所需的所有脚本都在 这个仓库中。
关于 fd 的速度,很大一部分功劳要归于 regex 和 ignore crate,它们也用于 ripgrep(欢迎了解!)。
故障排除
fd 找不到我的文件!
请记住,fd 默认会忽略隐藏目录和文件。它还会忽略 .gitignore 文件中的模式。如果想确保找到所有可能的文件,请始终使用选项 -u/--unrestricted(或使用 -HI 启用对隐藏文件和被忽略文件的搜索):
> fd -u …
还请记住,fd 默认只根据文件名搜索,不会将模式与完整路径进行匹配。如果想根据完整路径搜索(类似于 find 的 -path 选项),需要使用 --full-path(或 -p)选项。
彩色输出
fd 可以像 ls 一样根据扩展名为文件着色。要启用此功能,必须设置环境变量 LS_COLORS。通常,可以通过 dircolors 命令设置此变量的值;该命令提供了一种便捷的配置格式,用于为不同文件格式定义颜色。
在大多数发行版中,LS_COLORS 应该已经设置。如果你使用的是 Windows,或者想寻找其他更完整(或色彩更丰富)的版本,请参阅这里、这里或这里。
fd 也会遵循 NO_COLOR 环境变量。
fd 似乎无法正确解析我的正则表达式模式
许多正则表达式特殊字符(如 []、^、$ 等)在 shell 中也是特殊字符。如有疑问,请始终用单引号括起正则表达式模式:
> fd '^[A-Z][0-9]+$'
如果模式以短横线开头,必须添加 -- 来标记命令行选项的结束。否则,该模式会被解释为命令行选项。另一种方法是使用只包含一个连字符的字符类:
> fd -- '-pattern'
> fd '[-]pattern'
alias 或 shell 函数提示“Command not found”
通过 fd -x 或 fd -X 执行命令时,不能使用 shell alias 和 shell 函数。在 zsh 中,可以通过 alias -g myalias="…" 将别名设为全局别名。在 bash 中,可以使用 export -f my_function 使函数可供子进程使用。但你仍然需要调用 fd -x bash -c 'my_function "$1"' bash。对于其他用例或 shell,请使用(临时)shell 脚本。
-x/-X 中的占位符
根据所用的 shell,你可能需要将占位符({}、{/}、{//}、{.}、{/.})括在引号中,以防 shell 在 fd 看到它们之前先行解析。
与其他程序集成
将 fd 与 fzf 配合使用
你可以使用 fd 为命令行模糊查找工具 fzf 生成输入:
export FZF_DEFAULT_COMMAND='fd --type file'
export FZF_CTRL_T_COMMAND="$FZF_DEFAULT_COMMAND"
然后,你可以在终端中输入 vim <Ctrl-T>,打开 fzf 并搜索 fd 的结果。
或者,你可能想要跟随符号链接并包含隐藏文件(但排除 .git 文件夹):
export FZF_DEFAULT_COMMAND='fd --type file --follow --hidden --exclude .git'
你甚至可以通过设置以下内容,在 fzf 中使用 fd 的彩色输出:
export FZF_DEFAULT_COMMAND="fd --type file --color=always"
export FZF_DEFAULT_OPTS="--ansi"
更多详情,请参阅 fzf README 的 Tips 部分。
将 fd 与 rofi 配合使用
rofi 是一个图形化启动菜单应用,可以通过读取 stdin 创建菜单。将 fd 的输出传入 rofi 的 -dmenu 模式,即可创建可进行模糊搜索的文件和目录列表。
示例
在 $HOME 目录下创建一个不区分大小写、可多选的 PDF 文件搜索列表,并使用已配置的 PDF 查看器打开所选文件。若要列出所有文件类型,请删除 -e pdf 参数。
fd --type f -e pdf . $HOME | rofi -keep-right -dmenu -i -p FILES -multi-select | xargs -I {} xdg-open {}
要修改 rofi 显示的列表,请为 fd 命令添加参数。要修改 rofi 的搜索行为,请为 rofi 命令添加参数。
在 emacs 中使用 fd
emacs 软件包 find-file-in-project 可以 使用 fd 查找文件。
安装 find-file-in-project 后,将 (setq ffip-use-rust-fd t) 添加到
~/.emacs 或 ~/.emacs.d/init.el 文件中。
在 emacs 中,运行 M-x find-file-in-project-by-selected 查找匹配的文件。或者,运行
M-x find-file-in-project 列出项目中的所有可用文件。
将输出打印为树形结构
若要将 fd 的输出格式化为文件树,可以使用带有
--fromfile 的 tree 命令:
❯ fd | tree --fromfile
这可能比直接运行 tree 更实用,因为 tree 默认不会忽略任何文件,而且它也不支持像
fd 那样丰富的选项来控制输出内容:
❯ fd --extension rs | tree --fromfile
.
├── build.rs
└── src
├── app.rs
└── error.rs
在 bash 等类似环境中,你可以直接创建一个别名:
❯ alias as-tree='tree --fromfile'
将 fd 与 xargs 或 parallel 搭配使用
请注意,fd 内置了命令执行功能,可使用
-x/--exec 和 -X/--exec-batch 选项。如果你更喜欢,也仍然可以将它与
xargs 搭配使用:
> fd -0 -e rs | xargs -0 wc -l
这里,-0 选项会让 fd 使用 NULL 字符(而非换行符)分隔搜索结果。同样,xargs 的
-0 选项会让它以这种方式读取输入。
安装
在 Ubuntu 上
……以及其他基于 Debian 的 Linux 发行版。
如果你运行的是 Ubuntu 19.04(Disco Dingo)或更新版本,可以安装 官方维护的软件包:
apt install fd-find
请注意,由于二进制名称 fd 已被另一个软件包使用,该二进制文件名为 fdfind。
建议安装后运行命令 ln -s $(which fdfind) ~/.local/bin/fd,为 fd 创建链接,
以便像本文档中所述那样使用 fd。请确保 $HOME/.local/bin 位于你的 $PATH 中。
如果你使用的是较旧版本的 Ubuntu,可以从
发布页面下载最新的 .deb 软件包,并通过以下方式安装:
dpkg -i fd_9.0.0_amd64.deb # adapt version number and architecture
请注意,本项目发布页面上的 .deb 软件包仍将可执行文件命名为 fd。
在 Debian 上
如果你运行的是 Debian Buster 或更新版本,可以安装 官方维护的 Debian 软件包:
apt-get install fd-find
请注意,由于二进制名称 fd 已被另一个软件包使用,该二进制文件名为 fdfind。
建议安装后运行命令 ln -s $(which fdfind) ~/.local/bin/fd,为 fd 创建链接,
以便像本文档中所述那样使用 fd。请确保 $HOME/.local/bin 位于你的 $PATH 中。
请注意,本项目发布页面上的 .deb 软件包仍将可执行文件命名为 fd。
在 Fedora 上
从 Fedora 28 开始,你可以从官方软件包源安装 fd:
dnf install fd-find
在 Alpine Linux 上
只要启用了相应的软件仓库,你就可以从官方源安装 fd 软件包:
apk add fd
在 Arch Linux 上
你可以从官方软件仓库安装 fd 软件包:
pacman -S fd
你也可以从 AUR安装 fd。
在 Gentoo Linux 上
你可以使用官方软件仓库中的 fd ebuild:
emerge -av fd
在 openSUSE Linux 上
你可以从官方软件仓库安装 fd 软件包:
zypper in fd
在 Void Linux 上
你可以通过 xbps-install 安装 fd:
xbps-install -S fd
在 ALT Linux 上
你可以从官方软件仓库安装 fd 软件包:
apt-get install fd
在 Solus 上
你可以从官方仓库安装 fd 软件包:
eopkg install fd
在 RedHat Enterprise Linux (RHEL) 8/9/10、Almalinux 8/9/10、EuroLinux 8/9 或 Rocky Linux 8/9/10 上
你可以从 Fedora Copr 安装 fd 软件包。
dnf copr enable tkbcopr/fd
dnf install fd
EPEL8/9 仓库也提供另一个版本的软件包 fd-find,该版本使用较慢的 malloc,而非 jemalloc。
在 macOS 上
你可以使用 Homebrew 安装 fd:
brew install fd
……也可以使用 MacPorts:
port install fd
在 Windows 上
你可以从发布页面下载预构建二进制文件。
或者,你可以通过 Scoop 安装 fd:
scoop install fd
也可以通过 Chocolatey:
choco install fd
也可以通过 Winget:
winget install sharkdp.fd
在 GuixOS 上
你可以从官方仓库安装 fd 软件包:
guix install fd
在 Mise 上
你可以使用 mise 通过类似下面的命令安装 fd:
mise use -g fd@latest
在 NixOS 上/通过 Nix 安装
你可以使用 Nix 包管理器安装 fd:
nix-env -i fd
通过 Flox 安装
你可以使用 Flox 将 fd 安装到 Flox 环境中:
flox install fd
在 FreeBSD 上
你可以从官方仓库安装 fd-find 软件包:
pkg install fd-find
从 npm 安装
在 Linux 和 macOS 上,你可以安装 fd-find 软件包:
npm install -g fd-find
从源代码构建
使用 Rust 的包管理器 cargo,你可以通过以下方式安装 fd:
cargo install fd-find
请注意,需要 Rust 版本 1.90.0 或更高版本。
构建还需要 make。
从二进制文件安装
发布页面提供适用于 Linux、macOS 和 Windows 的预编译二进制文件。也提供静态链接的二进制文件:请查找文件名中带有 musl 的压缩包。
开发
git clone https://github.com/sharkdp/fd
# Build
cd fd
cargo build
# Run unit tests and integration tests
cargo test
# Install
cargo install --path .
补全
从发布压缩包获取
发布压缩包(.tar.gz/.zip)中附带预构建的补全文件,可在发布页面的 autocomplete 目录中找到。
使用这些补全文件的方法如下:
- bash:在
~/.bashrc中加载fd.bash文件,或将其放入会自动加载的目录中。 - zsh:将
_fd移至fpath中的目录(例如~/.zfunc)。 - fish:将
fd.fish复制到~/.config/fish/completions/。 - powershell:从某个配置文件脚本加载
_fd.ps1。
从 fd 生成
你也可以直接使用 fd --gen-completions <shell> 生成补全文件:
# Bash
fd --gen-completions bash > ~/.local/share/bash-completion/completions/fd
# Zsh (ensure ~/.zfunc is in your fpath)
fd --gen-completions zsh > ~/.zfunc/_fd
# Fish
fd --gen-completions fish > ~/.config/fish/completions/fd.fish
# PowerShell
fd --gen-completions powershell >> $PROFILE
维护者
许可证
fd 根据 MIT License 和 Apache License 2.0 的条款发行。
有关许可详情,请参阅 LICENSE-APACHE 和 LICENSE-MIT 文件。