#搜索模式 #查找 #文件 #文件搜索 #查找文件 #目录 #文件扩展名

程序+库 fd-find-enhance

fd 是 find 的简单、快速且用户友好的替代品

4 个稳定版本

10.1.1026 2024 年 7 月 17 日
10.1.1025 2024 年 7 月 16 日

#304命令行工具

Download history 301/week @ 2024-07-16 32/week @ 2024-07-23

333 每月下载量

MIT/Apache

200KB
4K SLoC

fd

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

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

安装使用方法故障排除

赞助商

特别感谢我们的主要 赞助商

Terminal Trove
终端中所有事物的 $HOME。

在 Terminal Trove 中找到您的下一个 CLI / TUI 工具和其他工具。
在我们的通讯中获取新工具的更新。

特性

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

演示

Demo

如何使用

首先,要查看所有可用的命令行选项,您可以通过运行 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 -p -g '**/.git/config'
> fd -p '.*/lesson-\d+/[a-z]+.(jpg|png)'

命令执行

除了显示搜索结果外,您通常还想要对它们进行操作。 fd 提供了两种方式来为您搜索结果的每个结果执行外部命令

  • -x/--exec 选项为每个搜索结果运行一个外部命令,它们是 并行 运行的。
  • -/--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。这就是为什么我们将 - 选项放在最后的原因。

查找所有 test_*.py 文件并在您喜欢的编辑器中打开它们

fd -g 'test_*.py' -X vim

请注意,我们在这里使用大写的 - 来打开单个 vim 实例。如果有两个这样的文件,test_basic.pylib/test_advanced.py,这将运行 vim test_basic.py lib/test_advanced.py

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

fd -X ls -lhd --color=always

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

当将 fdripgrep (rg) 结合使用以在特定类别的文件中搜索时,- 选项也非常有用,例如所有 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

占位符语法

--选项接受一系列参数(而不是单个字符串)作为命令模板。如果您想在命令模板后添加额外的fd选项,可以使用\;来终止它。

生成命令的语法类似于GNU Parallel

  • {}:一个占位符,将被搜索结果的路径(例如:documents/images/party.jpg)替换。
  • {.}:与{}类似,但不含文件扩展名(例如:documents/images/party)。
  • {/}:一个占位符,将被搜索结果的基名(例如:party.jpg)替换。
  • {//}:发现路径的父路径(例如:documents/images)。
  • {/.}:不带扩展名的基名(例如:party)。

如果不包含占位符,fd会自动在末尾添加一个{}

并行执行与串行执行

对于-/--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

[!NOTE] 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 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]
  -h, --help                       Print help (see more with '--help')
  -V, --version                    Print version

基准测试

让我们搜索我的家目录中所有以[0-9].jpg结尾的文件。它包含约750,000个子目录和约4000万个文件。为了平均和统计分析,我使用了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 的速度,很多功劳要归功于那些在 ripgrep(去看看!)中也被使用的 regexignore 仓库。

故障排除

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'

alias 或 shell 函数的 "命令未找到" 错误

Shell 的别名(alias)和函数不能用于通过 fd -xfd -X 执行命令。在 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 命令添加参数。

使用 fd 与 emacs

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 的输出格式化为文件树,可以使用带有 --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-/--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/fdfd 添加一个链接,以便像本文档中一样使用 fd。确保 $HOME/.local/bin 在您的 $PATH 中。

如果您使用的是较旧的 Ubuntu 版本,您可以从 发布页面 下载最新的 .deb 软件包,并通过以下方式安装:

dpkg -i fd_9.0.0_amd64.deb # adapt version number and architecture

在 Debian 上

如果您运行的是 Debian Buster 或更高版本,您可以安装 官方维护的 Debian 软件包

apt-get install fd-find

请注意,二进制文件名为 fdfind,因为 fd 已经被另一个软件包使用。建议安装后,通过执行命令 ln -s $(which fdfind) ~/.local/bin/fdfd 添加一个链接,以便像本文档中一样使用 fd。确保 $HOME/.local/bin 在您的 $PATH 中。

在 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

在 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 License 2.0 的条款下分发。

有关许可详情,请参阅 LICENSE-APACHELICENSE-MIT 文件。

依赖项

~11–23MB
~334K SLoC