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命令行工具

Download history 4716/week @ 2024-05-03 3496/week @ 2024-05-10 2493/week @ 2024-05-17 2556/week @ 2024-05-24 2593/week @ 2024-05-31 2371/week @ 2024-06-07 2040/week @ 2024-06-14 2286/week @ 2024-06-21 2078/week @ 2024-06-28 2072/week @ 2024-07-05 2183/week @ 2024-07-12 2002/week @ 2024-07-19 2039/week @ 2024-07-26 2003/week @ 2024-08-02 2207/week @ 2024-08-09 1788/week @ 2024-08-16

每月 8,410 次下载

MIT/Apache

200KB
4K SLoC

fd

CICD 版本信息 [中文] [한국어]

fd 是一个在文件系统中查找条目的程序。它是一个简单、快速且用户友好的 find 的替代品。虽然它并不旨在支持 find 的所有强大功能,但它为大多数用例提供了合理的(有偏见的)默认设置。

安装如何使用故障排除

特性

  • 直观的语法:使用 fd PATTERN 而不是 find -iname '*PATTERN*'
  • 正则表达式(默认)和基于通配符的模式。
  • 非常快速,因为并行遍历目录。
  • 使用颜色突出显示不同类型的文件(与 ls 相同)。
  • 支持 并行命令执行
  • 智能大小写:默认情况下搜索不区分大小写。如果模式包含大写字母,则切换到区分大小写*
  • 默认情况下忽略隐藏目录和文件。
  • 默认情况下忽略 .gitignore 中的模式。
  • 命令名比 find50% * :-)。

演示

Demo

如何使用

首先,要了解所有可用的命令行选项,您可以通过运行以下命令来获取简洁的帮助信息: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.zipbackup/file2.zip,则会执行 unzip file1.zipunzip 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.pylib/test_advanced.py,这将运行 vim test_basic.py lib/test_advanced.py

要查看文件权限、所有者、文件大小等信息,您可以告诉 fd 通过为每个结果运行 ls 来显示它们

fd -X ls -lhd --color=always

此模式非常有用,因此 fd 提供了一个快捷方式。您可以使用 -l/--list-details 选项以这种方式执行 lsfd … -l

当将 fdripgrep (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也支持其他程序(如rgag)使用的.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 rmfd 调用。或者,使用 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 -iregex23 倍,比 find -iname 快约 13 倍。顺便说一句,这两个工具找到了完全相同的 546 个文件 😄。

注意:这是在 一台特定机器上进行的 一个特定 基准测试。虽然我们已经进行了许多不同的测试(并发现了一致的结果),但结果可能会有所不同!我们鼓励每个人在自己的系统上尝试。请参阅 此存储库 以获取所有必要的脚本。

关于 fd 的速度,很多功劳要归功于 regexignore 仓库,这些仓库也用于 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 -xfd - 来执行命令。在 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 的输出为文件树,可以使用带有 --fromfiletree 命令。

 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 与 xargsparallel 结合使用

请注意,fd 有一个内置的命令执行功能,可以通过其 -x/--exec-X/--exec-batch 选项来实现。如果您愿意,仍然可以与 xargs 结合使用。

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

这里,-0 选项告诉 fd 使用空字符来分隔搜索结果(而不是换行符)。同样,xargs-0 选项告诉它以这种方式读取输入。

安装

Packaging status

在 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

您可以使用 Floxfd 安装到 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-APACHELICENSE-MIT 文件以获取许可证详情。

依赖项

约 10–21MB
约 312K SLoC