如果你每天在终端里敲 find . -name “*.py”,一定被它的括号、引号和转义折磨过。fd 是一个用 Rust 编写的现代化文件查找工具,它把最常见的查找场景浓缩成一个单词:默认递归、彩色输出、智能大小写,还会自动跳过 .gitignore 里的噪声。本文从安装到管道组合,带你把 fd 真正用起来。
一、为什么还要学 fd:find 的三道坎
find 是 POSIX 标配,几乎无处不在,但它的设计对交互场景并不友好。举个真实的尴尬场景:你想在当前项目里找所有名为 config 的文件,却要写成 find . -type f -name "*config*",少一个星号、多一对引号都会让你怀疑人生。更糟的是,find 默认会钻进 node_modules、.git 这些黑洞,输出一大堆你根本不关心的结果。
fd 正是为「人每天在终端里找文件」这个高频场景而生,它解决了 find 的三道坎:1)语法极简,一个模式搞定,不用记一堆 -name/-type/-print 开关;2)默认忽略 .gitignore 与隐藏目录,结果干净;3)彩色高亮、智能大小写,输出对人类友好。需要说明:fd 不是要取代 find 在脚本里的地位,而是替换你命令行里 90% 的交互式查找。
二、30 秒装好 fd
fd 是单静态二进制,安装成本极低,主流平台都有预编译包:
# macOS
brew install fd
# Ubuntu / Debian
sudo apt install fd-find
# 注意 Debian/Ubuntu 下命令名是 fdfind,可加别名 alias fd=fdfind
# 有 Rust 工具链
cargo install fd-find
# Windows (scoop / Chocolatey)
scoop install fd
choco install fd
装完后直接敲 fd --version 验证。下文所有示例均使用 fd 作为命令名;若你是 Debian/Ubuntu,请自行替换为 fdfind 或加上别名。
三、最朴素的查找:记住一个单词
想找文件名里包含某个词的,直接给一个模式即可,fd 会递归整棵目录树:
# 在当前目录递归查找文件名包含 config 的文件/目录
fd config
# 对比 find 的等价写法
find . -name '*config*'
差异一眼可见:fd 默认递归、按智能大小写匹配(全小写时忽略大小写,模式里含大写时变精确匹配)、并用颜色高亮命中部分。你不用再纠结 -name 要不要加星号,也不用担心漏写 ./。如果要按完整路径匹配而非仅文件名,可加 --full-path。
四、常用参数速查
下表是日常最高频的几个开关,记住它们就能覆盖绝大多数场景:
# 只找 Python 文件
fd -e py
# 找目录(不是文件)
fd -t d node_modules
# 深度不超过 2 层
fd -d 2 config
# 连隐藏文件一起找
fd -H secret
# 连被 gitignore 忽略的文件也查
fd -I secret
这些参数组合起来的可读性,明显优于 find 那一长串 -type f -name '*.py' -not -path。
五、正则与模式匹配
fd 的模式默认就是正则表达式(和 ripgrep 一致),比 glob 更灵活,也更符合程序员的直觉:
# 以 app 开头、以 .ts 结尾
fd '^app.*\.ts$'
# 以 log 结尾的任意文件
fd 'log$'
# 精确匹配某个文件名
fd '^exact-name$'
注意正则里的点要转义成 \.;如果你只想做普通子串匹配,直接用不含特殊字符的词即可,fd 会做子串查找。配合 --full-path,你甚至可以基于完整路径写正则,例如 fd --full-path 'src/.*\.py$' 只匹配 src 下的 Python 文件。
六、真正的威力:把 fd 接进管道
fd 的价值在组合。它输出的是干净的、可被其他命令消费的路径列表,天然适合接管道:
# 用 bat 预览所有 Markdown 文件
fd -e md --exec bat
# 把查到的 .py 文件一次性丢进 vim
fd -e py -X vim
# 批量删除临时文件
fd -e tmp -X rm
# 对查到的每个 Rust 文件,用 ripgrep 搜 TODO
fd -e rs -x rg 'TODO'
-x 是「逐条执行」,每条结果启动一次命令,适合需要独立处理的场景;-X 是「批量执行」,把所有结果作为参数一次性传给命令,适合 rm、vim、wc 这类能接收多文件的命令,效率更高。例如 fd -e py -X wc -l 可以一行统计所有 Python 文件行数。
七、和 find 正面刚:命令对照表
可以看出,凡是「交互式、按名/类型找文件」的场景,fd 都更短、更不易出错。
八、进阶玩法:预览、并行与 ls 风格
# 并行执行(默认即多线程),并对每个结果跑命令
fd -e go --exec -S du -sh
# ls -l 风格的详细列表
fd --list-details
# 配合 fzf 做交互式预览选择
fd --type f | fzf --preview 'bat --color=always {}'
--exec -S 表示并行执行命令;--list-details 给出类似 ls -l 的权限与大小信息;配合 VS Code 集成终端或 fzf,体验更佳。你还可以用 fd -t f | fzf 在大量文件里做交互式筛选,再用回车直接打开。
九、性能实测:fd 为什么快
fd 快并非玄学,主要来自三点:第一,默认忽略 .gitignore 和隐藏目录,少遍历大量无关文件;第二,Rust 实现的多线程并行遍历目录树,吃满多核;第三,智能大小写与正则引擎都做了优化。我们可以用同一项目简单对比:
# find 计时
time find . -name '*.rs' >/dev/null
# fd 计时
time fd -e rs >/dev/null
在含 node_modules 的中大型项目里,fd 常常比裸 find 快数倍,因为它直接跳过了被忽略的巨型目录。如果你确实需要翻遍每一个角落(包括被忽略的文件),加 -I 关闭忽略即可,只是会变慢——这正是「默认聪明」带来的收益。
十、和 ripgrep、VS Code 协同
fd 与 ripgrep(rg) 是同一作者的黄金搭档:一个管「按文件名找」,一个管「按文件内容搜」。分工明确——先用 fd -e rs 缩小范围,再 rg TODO 深入内容,比单用任何一个都高效。
在 VS Code 的集成终端里用 fd 定位文件后直接 code <文件> 打开;在 Docker 容器或 GitHub Actions 的 CI 步骤里,fd 也能作为轻量查找工具,用来收集待处理文件清单、批量做校验或打包。
十一、Shell 集成:把 fd 溶进工作流
把 fd 包成几个小函数,日常导航会顺手很多。下面这组定义在 bash/zsh 下即可用:
# 进入唯一匹配的目录(模糊)
fcd() { local d; d=$(fd -t d -d 3 "$1" | head -1) && cd "$d"; }
# 配合 fzf 交互式跳转
cdf() { local d; d=$(fd --type d | fzf) && cd "$d"; }
# 用默认编辑器打开匹配的文件
fe() { local f; f=$(fd --type f | fzf) && "${EDITOR:-vim}" "$f"; }
把上面几行写进 ~/.bashrc 或 ~/.zshrc 后,fcd config 就能一步跳进名字含 config 的目录,fe 则用模糊选择打开文件。fish 用户可以用 fd 配合 fzf 写成 function,体验同样丝滑。
十二、常见误区与排障
这几个坑基本覆盖了新手 90% 的困惑。记住「fd 默认是『聪明且干净』的查找」,需要时再显式打开忽略与隐藏开关。
十三、fd、rg、find 的黄金三角
最后用一句话收尾:把 fd 当成你终端里的「文件名搜索引擎」,把 ripgrep 当成「内容搜索引擎」,把 find 留在需要极致控制力的脚本里。三者各司其职、组合使用,你的命令行效率会肉眼可见地提升。下次再想敲 find,不妨先试试 fd——很可能一个单词就解决了。




