35 个稳定版本 (7 个主要版本)
新 10.2.0 | 2024 年 8 月 23 日 |
---|---|
10.1.0 | 2024 年 5 月 8 日 |
9.0.0 | 2023 年 12 月 19 日 |
8.7.1 | 2023 年 10 月 21 日 |
3.1.0 | 2017 年 9 月 17 日 |
#2 在 命令行工具 中
每月 8,410 次下载
200KB
4K SLoC
fd
fd
是一个在文件系统中查找条目的程序。它是一个简单、快速且用户友好的 find
的替代品。虽然它并不旨在支持 find
的所有强大功能,但它为大多数用例提供了合理的(有偏见的)默认设置。
特性
- 直观的语法:使用
fd PATTERN
而不是find -iname '*PATTERN*'
。 - 正则表达式(默认)和基于通配符的模式。
- 非常快速,因为并行遍历目录。
- 使用颜色突出显示不同类型的文件(与
ls
相同)。 - 支持 并行命令执行
- 智能大小写:默认情况下搜索不区分大小写。如果模式包含大写字母,则切换到区分大小写*。
- 默认情况下忽略隐藏目录和文件。
- 默认情况下忽略
.gitignore
中的模式。 - 命令名比
find
短 50% * :-)。
演示
如何使用
首先,要了解所有可用的命令行选项,您可以通过运行以下命令来获取简洁的帮助信息:fd -h
,或者获取更详细的版本,请运行:fd --help
。
简单搜索
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
-
选项可以与搜索模式结合使用。
> fd -e rs mod
src/fshelper/mod.rs
src/lscolors/mod.rs
tests/testenv/mod.rs
搜索特定文件名
要查找与提供的搜索模式完全匹配的文件,请使用 -
(或 --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
模式的文件夹(并显示文件)。要禁用此行为,我们可以使用 -
(或 --no-ignore
)选项。
> fd num_cpu
> fd -I num_cpu
target/debug/deps/libnum_cpus-f5ce7ef99006aa05.rlib
要真正搜索 所有 文件和目录,只需将隐藏和忽略功能结合起来显示所有内容(-HI
)或使用 -
/--unrestricted
。
匹配完整路径
默认情况下,fd 只匹配每个文件的文件名。但是,使用 --full-path
或 -
选项,您可以匹配完整路径。
> fd -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
选项放在最后的原因。
查找所有 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
) 结合使用以在特定类别的文件中进行搜索时,例如所有 C++ 源文件,-X
选项也非常有用
fd -e cpp -e cxx -e h -e hpp -X rg 'std::cout'
将所有 *.jpg
文件转换为 *.png
文件
fd -e jpg -x convert {} {.}.png
这里,{}
是搜索结果的占位符。 {.}
同样是,但没有文件扩展名。下面有更多关于占位符语法的详细信息。
使用 -
并行执行命令的终端输出不会交错或混乱,因此可以使用 fd -
来粗略地并行化跨许多文件运行的任务。一个例子是计算目录中每个单独文件的校验和。
fd -tf -x md5sum > file_checksums.txt
占位符语法
选项 -
和 -
使用一系列参数(而不是单个字符串)作为 命令模板。如果您想在命令模板之后添加额外的 fd
选项,则可以使用 \;
结束它。
生成命令的语法类似于 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 <pattern> 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 file 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]
-h, --help Print help (see more with '--help')
-V, --version Print version
基准测试
让我们在我的主目录中搜索以 [0-9].jpg
结尾的文件。它包含约 75 万个子目录和大约 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 个文件 😄。
注意:这是在 一台特定机器上进行的 一个特定 基准测试。虽然我们已经进行了许多不同的测试(并发现了一致的结果),但结果可能会有所不同!我们鼓励每个人在自己的系统上尝试。请参阅 此存储库 以获取所有必要的脚本。
关于 fd 的速度,很多功劳要归功于 regex
和 ignore
仓库,这些仓库也用于 ripgrep(去看看吧!)。
故障排除
fd
找不到我的文件!
请记住,默认情况下 fd
会忽略隐藏的目录和文件。它还会忽略 .gitignore
文件中的模式。如果您想确保找到所有可能的文件,请始终使用选项 -u
/--unrestricted
(或使用 -HI
启用隐藏和忽略的文件)
> fd -u …
彩色输出
fd
可以通过扩展名对文件进行着色,就像 ls
。为了让这生效,必须设置环境变量 LS_COLORS
。通常,这个变量的值由 dircolors
命令设置,它提供了一个方便的配置格式来定义不同文件格式的颜色。在大多数发行版中,LS_COLORS
应该已经设置。如果您使用 Windows 或在寻找替代方案,更完整(或更丰富多彩)的变体,请参阅 这里、这里 或 这里。
fd
也会尊重 NO_COLOR
环境变量。
fd
似乎没有正确解析我的正则表达式模式
很多特殊正则表达式字符(如 []
、^
、$
等)在您的 shell 中也是特殊字符。如果有疑问,请始终确保将正则表达式模式放在单引号中
> fd '^[A-Z][0-9]+$'
如果您的模式以连字符开头,您必须添加 --
以表示命令行选项的结束。否则,模式将被解释为命令行选项。或者,可以使用包含单个连字符字符类的选项
> fd -- '-pattern'
> fd '[-]pattern'
别名或 shell 函数的 "找不到命令"
shell 的 alias
和 shell 函数不能通过 fd -x
或 fd -
来执行命令。在 zsh
中,您可以通过 alias -g myalias="…"
使别名全局。在 bash
中,您可以使用 export -f my_function
使其在子进程中可用。您仍然需要调用 fd -x bash -c 'my_function "$1"' bash
。对于其他用例或 shell,请使用一个(临时)shell 脚本。
与其他程序的集成
使用 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 中的 技巧部分。
使用 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
后,将以下行添加到您的 ~/.emacs
或 ~/.emacs.d/init.el
文件中:(setq ffip-use-rust-fd t)
在 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 使用空字符来分隔搜索结果(而不是换行符)。同样,xargs
的 -0
选项告诉它以这种方式读取输入。
安装
在 Ubuntu 上
... 以及其他基于 Debian 的 Linux 发行版。
如果您运行的是 Ubuntu 19.04(Disco Dingo)或更高版本,您可以安装官方维护的 软件包
apt install fd-find
请注意,二进制文件被命名为 fdfind
,因为二进制名称 fd
已经被另一个软件包使用。建议在安装后,通过执行以下命令 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
请注意,二进制文件被命名为 fdfind
,因为二进制名称 fd
已经被另一个软件包使用。建议在安装后,通过执行以下命令 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 8/9 (RHEL8/9)、Almalinux 8/9、EuroLinux 8/9 或 Rocky Linux 8/9 上
您可以从 Fedora Copr 安装 fd 软件包
dnf copr enable tkbcopr/fd
dnf install fd
还有使用更慢的 malloc(而不是 jemalloc)的不同版本,该版本也作为 fd-find
软件包从 EPEL8/9 仓库中提供。
在 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
在 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.77.2 或更高版本。
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 .
维护者
许可证
fd
在 MIT 许可证和 Apache 许可证 2.0 的条款下分发。
请参阅 LICENSE-APACHE 和 LICENSE-MIT 文件以获取许可证详情。
依赖项
约 10–21MB
约 312K SLoC