查找+ grep作为if条件不能按预期工作

问题描述

我使用find获取所有txt文件,然后使用grep来查找txt文件中是否有一个特殊单词,这些单词是通过find命令找到的

if find "/home/test/" -name "*.csv" -exec grep "pattern" {} \;; then
    echo "find it in txt files";
else
    echo "not find in txt files";
fi

尽管不满足条件,程序始终输出"find it"

解决方法

除非用加号标点,否则 -exec 谓词不会影响查找的退出状态。参见:

$ find . -prune -exec test -f {} ';'
$ echo $?
0
$ find . -prune -exec test -f {} '+'
$ echo $?
1

但即使带有加号,查找的退出状态也不可靠。由于内存限制,它可能会多次调用 grep ,并且如果以非零值退出任何调用,则 find 的退出状态也将为非零。换句话说,如果 grep 的所有调用都找到了匹配项,但没有找到匹配项,则 find 的退出状态将不会为零。这也适用于 xargs

这是解决这些限制的一种方法:

! find . -name '*.txt' -exec sh -c '! "$@"' _ grep 'pattern' /dev/null {} +
, 如果找到的所有文件都已处理,

find将正常退出。具体来说,这将忽略所执行命令的返回代码。

如果要使用退出代码grep,最好使用xargs,后者可以将find的输出作为命令行参数发送到grep 。例如:

find ./ -name '*.txt' -print0 | xargs -0r grep "pattern"

这样做的好处是,您仍然可以自定义find而不是grep -r来设置参数。

当然,您可以将GNU grep与--exclude--include结合使用以实现类似功能,但是find的表达式功能更强大。