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

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

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

答案1

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

find . ... -print -quit

NetBSD 的find等价物:

find . ... -print -exit

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

find . ... -print | head -n 1

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

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

(find . ... -print &) | head -n 1

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

find . ... -exec sh -c 'printf "%s\n" "$1"; kill -s PIPE "$PPID"' sh {} \;

(替换printf为您要对该文件执行的任何操作)。

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

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

答案2

find . -name something -print -quit

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

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

find . -name something -print | head -n 5

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

测试起来非常容易。只需让 find 搜索A在 root 上,这将导致数千甚至更多的匹配,同时至少需要一分钟或更长时间。但是当通过管道输入“head”时,“find”将在指定数量后终止线在 head 中定义(默认 head 显示 10,使用“head -n”指定行)。

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

答案3

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

find -name "myfile*" -exec echo "Found {} and Quit" \; -quit
Found ./myfile1 and Quit

但是当使用 -quit-执行:

find -name "myfile*" -quit -exec echo "Found {} and Quit" \;
# Nothing was executed

答案4

如果与 flag 一起使用, grep 也会返回-m,因此

find stuff | grep -m1 .

它将在 find 打印的第一行之后返回。

这之间的区别在于find stuff -print -quit | head -1,如果搜索足够快,grep 可能无法及时停止该过程(不过这并不重要),而如果搜索很长,它会节省 find 来打印大量不需要的内容线。

这与 busybox find 一起使用,尽管由于 busybox grep 也有-m它并不是真正需要的

find /tmp/stuff -exec "sh" "-c" "eval 'echo {}; { kill \$PPID; }'" \;

这将输出一条有关 find 进程已收到(通常)sigterm 信号的消息,但此输出属于正在运行的 shell,而不是 find 命令,因此它不会干扰命令输出,这意味着管道或重定向将仅输出该行通过查找匹配。

相关内容