【问题标题】:find + grep as an if condition doesn't work as expectedfind + grep 作为 if 条件不能按预期工作
【发布时间】:2020-08-20 11:50:58
【问题描述】:

我使用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"

【问题讨论】:

  • -name 必须被引用以防止 shell globbing。要获得退出状态,您可以使用 \( -exec grep ... {} \; -a -exec echo ... \; \)
  • 这能回答你的问题吗? Bash - find exec return value
  • 如果pattern 在任何文件中匹配,或者在所有文件中都匹配,您是否要打印find it

标签: shell grep find


【解决方案1】:

find 如果找到的所有文件都已处理,则正常退出。具体来说,这会忽略执行命令的返回码。

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

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

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

当然,您可以将 GNU grep 与 --exclude--include 一起使用以获得类似的功能,但 find 的表达式更强大。

【讨论】:

  • 谢谢,我尝试使用命令if find ./ -maxdepth 1 -name '*asdfasd*.txt' -print0 | xargs -0r grep "asdfqwerytavasdf" ; then echo "find it"; else echo "not find"; fi 来测试它是否正确。我发现如果find 命令返回一个空文件列表,控制台会显示find it,但我喜欢它显示not find。如何处理这个问题?
  • 我调试if 命令?所以我先在控制台输入find ./ -maxdepth 1 -name '*asdfasd*.txt' -print0 | xargs -0r grep "asdfqwerytavasdf",然后输入echo $?,控制台输出0,我对这个结果很困惑,因为输出是0,上面if命令需要输出not find跨度>
  • 我写了一个shell程序,发现if命令中的空变量为真...
【解决方案2】:

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

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

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

这是绕过这些限制的一种方法:

! find . -name '*.txt' -exec sh -c '! "$@"' _ grep 'pattern' /dev/null {} +

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-13
    相关资源
    最近更新 更多