我正试图找到一种可靠的方法来停止/杀死10场比赛后的查找操作。下面的代码是一个不太优雅的例子。
find . -type f -iname "*.txt" -exec myscript.sh {} ;
其中myscript.sh目前只输出文件名match
我已经尝试了一些建议在这里找到,例如管道到头部-n 10或管道到grep -m 10。但这些并不能可靠地阻止发现。
是否有可靠的方法?
我试过了,没有成功:
find . -type f -iname "*.txt" -exec myscript.sh {} ; | head -n 10
find . -type f -iname "*.txt" -exec myscript.sh {} ; | head -n 10 && tail -f /var/log/kern.log & read -t 10 ;kill $!
find . -type f -iname "*.txt" -exec myscript.sh {} ; | grep -m .
您无法阻止find
命令在终止之前生成超过10个匹配。shell并行运行find
和head
,find
可以很容易地在其输出缓冲区中排队输出10行以上,然后才被shell终止管道。
可以做的是重构管道,以防止出现任何症状。例如,
find . -type f -iname "*.txt" -print0 |
head -z -n 10 |
xargs -r0 myscript.sh
这依赖于几个GNU扩展(即,find
的-print0
选项打印文件名以空结束,head
的相应-z
选项,xargs
的相应-0
选项),所以它是不可移植的,但应该在大多数Linux发行版以及其他地方工作,如果你安装了GNU版本的标准实用程序(可能称为gfind
,ghead
,gxargs
等)。
null终止对鲁棒性很重要;如果你有包含换行符的文件名,head
等人可以在中间截断文件名,当然,xargs
不能知道一些换行符是文件名的一部分,而不是参数分隔符。即使您目前没有任何文件名包含换行符,您也要防止这种情况发生,因为任何解决方案都不是一次性的-稍后当您遇到包含换行符的文件名时,故障排除将是冗长而复杂的。也可参见https://mywiki.wooledge.org/BashFAQ/020
或者重构-exec
:
find . -type f -iname "*.txt" -exec sh -c '
for arg in $(seq 10); do
myscript.sh "$1"
shift
done
exit 222' _ {} +
exit 222
应该导致find
在第一次-exec
调用后失败而中止。-exec
之后的+
使find
传递尽可能多的参数,类似于xargs
。(如果文件名真的长,并且/或者您的系统的ARG_MAX
真的很小,那么在第一次调用中可能接收不到10个文件,但我认为这种情况是病态的。)
使用parallel,这符合我的要求
find . -type f -iname "*.txt" | head -n 10 | parallel -j1 'myscript.sh {} '