第一次匹配后如何停止查找命令?

cof*_*Mug 166 find command

有没有办法强制find命令在找到第一个匹配项后立即停止?

Sté*_*las 192

对于 GNU 或 FreeBSD find,您可以使用-quit谓词:

find . ... -print -quit
Run Code Online (Sandbox Code Playgroud)

NetBSDfind等效项:

find . ... -print -exit
Run Code Online (Sandbox Code Playgroud)

如果您所做的只是打印名称,并假设文件名不包含换行符,则可以执行以下操作:

find . ... -print | head -n 1
Run Code Online (Sandbox Code Playgroud)

这不会find在第一场比赛后停止,但可能取决于第二场比赛或(很久)之后的时间和缓冲。基本上,find当它尝试输出某些东西而head已经消失时,将用 SIGPIPE 终止,因为它已经读取并显示了第一行输入。

请注意,并非所有 shell 都会findhead返回后等待该命令。Bourne shell 和 AT&T 实现ksh(非交互式时)和yash(仅当该管道是脚本中的最后一个命令时)不会,使其在后台运行。如果您希望在任何 shell 中看到这种行为,您可以随时将上述内容更改为:

(find . ... -print &) | head -n 1
Run Code Online (Sandbox Code Playgroud)

如果您要做的不仅仅是打印找到的文件的路径,您可以尝试这种方法:

find . ... -exec sh -c 'printf "%s\n" "$1"; kill -s PIPE "$PPID"' sh {} \;
Run Code Online (Sandbox Code Playgroud)

(替换printf为您对该文件所做的任何操作)。

这具有find返回退出状态的副作用,这反映了它已被杀死的事实。

我们发送 SIGPIPE 信号而不是默认的 SIGTERM 以避免当管道的一部分被信号杀死时某些 shell 显示的消息。他们通常不会因为 SIGPIPE 的死亡而这样做,因为这些是自然发生的(find | head如上所示......)。

  • 如果有人需要测试任何文件是否与谓词匹配,一旦找到就停止,在 Bash 和 GNU Find 中你可以这样做:`if [[ $(find ... -print -quit) ]]; then ...` 它只是测试 find 是否打印了任何东西。 (3认同)
  • @Tobia,`[` 是标准命令。与其说是可怕的命令,不如说是类似 Bourne 的 shell 解析命令行的方式。`[[...]]` 是一个 ksh 结构,它在各种 shell 中都有自己的问题。例如,直到最近 `[[ $(...) ]]` 不能在 `zsh` 中工作(你需要 `[[ -n $(...) ]]`)。除了在 `zsh` 中,你需要在 `[[ $a = $b ]]` 中加引号,`[[ =~ ]]` 在实现之间甚至 bash 版本之间存在不兼容的差异,并且在某些方面存在一些错误。就个人而言,我更喜欢`[`。 (2认同)

小智 17

find . -name something -print -quit
Run Code Online (Sandbox Code Playgroud)

在打印后的第一个匹配项后终止查找。

在特定数量的匹配后终止查找并打印结果:

find . -name something -print | head -n 5
Run Code Online (Sandbox Code Playgroud)

令人惊讶的是 - head 现在在 5 次匹配后终止字符串,尽管我不知道如何或为什么。

这很容易测试。只需让 find search a on root 就可以得到数千个甚至更多的匹配项,同时至少需要一分钟或更长时间。但是当管道输入“head”时,“find”将在 head 中定义的指定行数后终止(默认 head 显示 10,使用“head -n”来指定行)。

请注意,这将在“head -n”达到指定的换行符计数后终止,因此任何包含多个换行符的匹配都将相应计数。


Noa*_*nos 6

运行 find 时,请在 后面加上-execuse ,否则命令执行将被跳过。例如:-quit\;

find -name "myfile*" -exec echo "Found {} and Quit" \; -quit
Found ./myfile1 and Quit
Run Code Online (Sandbox Code Playgroud)

但是当在 -exec之前使用 -skip 时:

find -name "myfile*" -quit -exec echo "Found {} and Quit" \;
# Nothing was executed
Run Code Online (Sandbox Code Playgroud)