如何检测“发现”是否找到任何匹配项?


16

是否有惯用的手段来检测“查找”是否找到了匹配项?我目前正在使用

COUNT=`find ... | wc -l`
if [ "$COUNT" -gt 0 ]; then

但这对我来说似乎是间接的。另外,我想找到匹配后就停止搜索,这样就不会浪费时间和精力。我只需要知道是否有匹配的文件即可。

更新:我犯了一个错误,没有我前面的代码就写了我的问题:我用wc -l在另一种情况下,无论如何我都需要知道找到的文件总数。如果我仅测试是否有匹配项,则使用if [ -z $(find …) ]

Answers:


17

如果您知道有GNU查找,请使用-quit 使其在第一个匹配项后停止。

可移植地,将的输出通过管道传递findhead -n 1。这样find,在几次匹配之后(当填充了head输入缓冲区时),它将因管道破裂而死亡。

无论哪种方式,您都不需要wc测试字符串是否为空,shell可以自行执行。

if [ -n "$(find … | head -n 1)" ]; then …

有趣的是...我以为-n只适用于“定义的”变量($ abc,$ xyz等),但我想$(...)是一个“定义的”临时变量。+1 ...(我只是最近读到,使用-n是有风险的,除非您确定该变量尚未声明且未使用。...但是临时不会有这种可能性...即。未初始化与空白
Peter.O 2011年

2
@fred:相反,-n测试字符串是否为空,它与变量无关。您所读的内容可能是在使用using -n不会测试是否定义了变量:-n "$foo"如果foo已定义,则为false,但为空,并在下方显示错误消息set -u[ -n "${foo+1}" ]可靠地测试是否foo设置了,但是对空和未设置的变量进行相同的处理通常是一个好主意:[ -n "${foo:+1}" ],或者[ -n "$foo" ]即使您不担心set -u
吉尔(Gilles)'所以

谢谢!我没有-quit空,但是管道可以head -n 1工作(就像一样head -c 1,它甚至更早就停止了,但是收益可能微不足道)。同样,我犯了一个错误,即在我面前没有代码的情况下写问题:我wc -l在另一种情况下使用,我需要知道找到的文件总数。如果我仅测试是否有匹配项,则使用if [ -z `find … ` ]
克里斯·佩奇

6

您可以使用该-quit操作在第一个比赛之后停止。您可能希望将其与另一个操作(例如-print)结合起来,否则将无法判断它是否找到了任何东西。

例如,find ... -print -quit将打印第一个匹配文件的路径,然后退出。或者,-printf 1 -quit如果有匹配项,则可以打印1,如果没有匹配项,则不打印任何内容。

find的退出状态反映了搜索时是否有错误,而不是是否发现任何东西,因此您必须检查其输出以查看是否存在匹配项。


-quit是GNU扩展。它不适用于使用find(1)的其他实现的系统,例如OS X,BSD和大多数商用Unices。
沃伦·杨

谢谢,如果我使用其他系统,这很有用。不幸的是,我的(Mac OS X)上-quit和-printf都不可用。
克里斯·佩奇

4

退出0很容易找到,而退出> 0则更困难,因为这通常仅在发生错误时发生。但是,我们可以实现它:

if find -type f -exec false {} +
then
  echo 'nothing found'
else
  echo 'something found'
fi

请注意,该解决方案比使用子外壳更有效。执行false肯定比执行Dash还要快:

$ cat alfa.sh bravo.sh charlie.sh delta.sh
find -name non-existing-file -exec false {} +
find -name existing-file -exec false {} +
[ "$(find -name non-existing-file)" ]
[ "$(find -name existing-file)" ]

$ strace dash alfa.sh | wc -l
807

$ strace dash bravo.sh | wc -l
1141

$ strace dash charlie.sh | wc -l
1184

$ strace dash delta.sh | wc -l
1194

0

您可以将其包装到shell条件中,例如:

[ "$(find . ...)" '!=' '' ] && echo Found || echo Not found

...您的比赛条件在哪里,例如-name *.txt

其他一些例子:

[ "$(find /etc -name hosts)" ] && echo True || echo False
[ ! -z "$(find /etc -name hosts)" ] && echo True || echo False
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.