有没有办法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 时,请在后面加上-exec
use ,否则命令执行将被跳过。例如:-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 命令,因此它不会干扰命令输出,这意味着管道或重定向将仅输出该行通过查找匹配。