使用任意表达式或命令查找过滤器

使用任意表达式或命令查找过滤器

问题:

find使用命令或替代方法打印满足以 shell 表达式表示的任意条件的文件(路径)集。

前任:有一个名为 ca.crt 的证书文件,其 OU(组织单位)可以是 openshift,以下表达式将返回状态代码 0(如果为 true),否则返回 0。

openssl x509 -in ca.crt -text -noout 2>/dev/null | grep "OU = openshift" > /dev/null

如何使用此表达式和命令find来查找给定目录树下组织单位为“openshift”的所有证书文件?

我看过:

页面-exec中的选项,其内容如下,findman

-exec command ;
              Execute command; true if 0 status is returned....

我不明白这个特定的声明:“如果返回 0 状态则为 true”。这是否意味着find如果特定文件的命令执行返回 0 状态,则认为该文件匹配 (true`)?这对解决问题有什么用吗?

问题:

如果不编写 shell 脚本,最简单的方法是什么?一艘班轮将是理想的选择。

答案1

我们想要在这里做的是使用带有-execin 的管道find作为测试,即类似

find /search/path -type f -name ca.crt -exec something {} \; -print

如果应打印路径名,则其中something返回退出状态为零。

现在,我们不能find直接使用管道,但我们可以让它调用sh -c

find /search/path -type f -name ca.crt -exec sh -c '
    openssl x509 -in "$1" -text -noout 2>/dev/null |
    grep -F -q "OU=openshift"' sh {} \; -print

这里发生的事情是find调用一个内联sh -c脚本来执行您的管道(我只做了轻微的更改)。如果管道以零退出状态退出(如果grep -q在 的输出中找到文本模式,则会执行此操作openssl),然后-print生效,并ca.crt打印具有该名称的常规文件的路径名。

文件的路径名ca.crt作为 传递到内联脚本中$1


一般来说,您使用的大多数谓词find测试, 包括-exec。如果一个测试通过对于特定的路径名​​,则考虑下一个测试。

在上面的命令中,测试是“该文件是常规文件吗?” ( -type f),“它的名字是什么ca.crt?” ( -name ca.crt),“如果我现在运行此命令,并{}替换为路径名,退出状态是否为零?” ( -exec ... \;)。最后-print的总是真的-print,因此如果进行的话,之后的任何进一步测试都将始终进行。


sh -c您可以通过一次为尽可能多的路径名调用脚本(而不是每个路径名一次)来使其效率稍微提高一些。然后,我们从内联脚本中打印路径名。

find /search/path -type f -name ca.crt -exec sh -c '
    for pathname do
        if openssl x509 -in "$pathname" -text -noout 2>/dev/null |
            grep -F -q "OU=openshift"
        then
            printf "%s\n" "$pathname"
        fi
    done' sh {} +

这是如何正确地使用来自 的路径名提供循环find

有关的:

相关内容