fd:代替 find 的命令行工具

fd 是一款语法简单、效率高、对用户友好的命令行查找工具,用以代替 GNU 的 find

虽然fd并不追求find强大的功能,但提供了大约 80% 常用的默认案例。

特性

  • 方便的语法:fd PATTERN 替换 find -iname '*PATTERN*'

  • 彩色终端输出(类似ls

  • 智能大小写:默认是大小写不敏感的,如果 pattern 包含大写字母则切换为大小写敏感

  • 默认忽略隐藏目录、文件

  • 默认忽略.gitignore里内容的文件或目录

  • 正则表达式

  • 识别 Unicode

  • 类似 GNU 并行执行命令的语法

并行执行命令

如果指定了-x/--exec选项以及一个命令模板,fd会创建一个并行执行命令的任务池,以每个找到的路径为输入。语法类似 GNU 并行执行。

  • {}:占位符,会被搜索结果的路径所代替(documents/images/party.jpg

  • {.}:没有文件扩展名的路径(documents/images/party

  • {/}:文件名(party.jpg

  • {//}:父路径(documents/images

  • {/.}:没有文件扩展名的文件名(party


# 转换所有 jpg 文件为 png 文件

fd -e jpg -x convert {} {.}.png



# 解压所有 zip 文件(如果没写占位符,自动在后面添加路径)

fd -e zip -x unzip



# 转换所有 flac 文件为 opus 文件

fd -e flac -x ffmpeg -i {} -c:a libopus {.}.opus



# 计算 Rust 文件的行数(命令模板可以用 ';' 终结,注意'\'转义:否则被 shell 认作两条语句)

fd -x wc -l \; -e rs

安装

在 Ubuntu 上

… 以及其他基于 Debian 的 Linux 分发版。

发布页面下载最新的.deb


sudo dpkg -i fd_7.0.0_amd64.deb # 自己适配版本号和架构

在 Arch Linux 上


pacman -S fd

在 Mac OS 上


brew install fd

或者用 MacPorts


sudo port install fd

在 Windows 上

发布页面下载二进制文件。

或者用Scoop


scoop install fd

或者用Chocolatey


choco install fd

从源安装

使用 Rust 的包管理器 Cargo,可以安装 fd:


cargo install fd-find

命令行选项


USAGE:

fd [FLAGS/OPTIONS] [<pattern>] [<path>...]



FLAGS:

-H, --hidden 搜索隐藏的文件和目录

-I, --no-ignore 不要遵守 .(git|fd) 忽略的文件

--no-ignore-vcs 不要遵守 .gitignore 忽略的文件

-s, --case-sensitive 大小写敏感搜索(默认:智能切换大小写敏感)

-i, --ignore-case 大小写不敏感搜索(默认:智能切换大小写敏感)

-F, --fixed-strings 将 pattern 识别为字面意思的字符串

-a, --absolute-path 以绝对路径显示,而不是相对路径

-L, --follow 跟踪符号链接

-p, --full-path 搜索全路径 (默认: 只有file-/dirname)

-0, --print0 通过 null 字符分离结果

-h, --help 打印帮助信息

-V, --version 打印版本信息



OPTIONS:

-d, --max-depth <depth> 设置最大搜索深度(默认:1)

-t, --type <filetype>... 通过类型过滤:文件(f),目录(d),符号链接(l),可执行文件(x)

-e, --extension <ext>... 通过文件扩展名过滤

-x, --exec <cmd> 对每个搜索结果执行一个命令

-E, --exclude <pattern>... 排除匹配 glob 模式的条目

--ignore-file <path>... 以 .gitignore 格式添加自定义忽略条目

-c, --color <when> 什么时候使用颜色: never, *auto*, always

-j, --threads <num> 设定搜索和执行的线程数



ARGS:

<pattern> 搜索的模式,一个正则表达式(可选)

<path>... 文件系统搜索的根目录(可选)

教程

简单搜索

最简单情况是用一个参数,即搜索模式:


> fd netfl

Software/python/imdb-ratings/netflix-details.py

从当前目录递归搜索包含 pattern netfl 的条目

正则表达式搜索


> cd /etc

> fd '^x.*rc$'

X11/xinit/xinitrc

X11/xinit/xserverrc

指定根目录

在特定目录下搜索,可以指定要搜索的根目录为第二个参数


> fd passwd /etc

/etc/default/passwd

/etc/pam.d/passwd

/etc/passwd

不用任何参数

递归遍历当前目录,类似ls -R


> cd fd/tests

> fd

testenv

testenv/mod.rs

tests.rs

指定文件扩展名


> cd fd

> fd -e md

CONTRIBUTING.md

README.md

-e选项也可以和 search pattern 结合起来:


> fd -e rs mod

src/fshelper/mod.rs

src/lscolors/mod.rs

tests/testenv/mod.rs

隐藏和忽略的文件

默认 fd 不会搜索隐藏目录,可用-H--hidden变比这个行为。


> fd pre-commit

> fd -H pre-commit

.git/hooks/pre-commit.sample

如果是在 Git 仓库搜索,fd 不会搜索匹配.gitignore模式的目录或文件,可用-I--no-ignore关闭这个行为。


> fd num_cpu

> fd -I num_cpu

target/debug/deps/libnum_cpus-f5ce7ef99006aa05.rlib

真的要搜索所有文件和目录,只要指定-HI即可。

排除特定的文件或目录


# 排除匹配 glob 模式的条目

> fd -H -E .git …

> fd -E /mnt/external-drive … # 排除特定的挂载目录

> fd -E '*.bak'# 排除特定的文件类型

要使 exclude-patterns 持久化,可以在 HOME 目录创建.fdignore文件,类似于.gitignore。这样 fd 的排除规则就永久生效了。


> cat ~/.fdignore

/mnt/external-drive

*.bak

伴随 xargs 或并行来使用 fd

如果想要对所有结果执行一条命令,可以用管道输出到xargs


> fd -0 -e rs | xargs -0 wc -l

这里-0选项用 NULL 字符将结果拼接(而不是默认的换行),xargs 同理用-0读取输入(用 NULL 分隔)

-x效果是等价的:


> fd -0 -e rs -x wc -l {}