为什么在 Linux 中使用 `-o` 时 `find` 会跳过预期结果?

为什么在 Linux 中使用 `-o` 时 `find` 会跳过预期结果?

为什么在 Linux(Debian 8)中

touch 1.cpp 1.h
find . -name "*.cpp" -o -name "*.h" -exec echo {} \;

1.h

find . -name "*.cpp" -o -name "*.h"

输出两者?这是错误还是功能?

答案1

我认为一旦您使用了-or运算符,那么您就必须保持它的一致性,以避免在使用逻辑或连接多个条件时出现逻辑运算顺序模糊的情况。

看起来该-exec部分与第二部分组合在一起-name "*.h"

因此,为了使其正常工作,您必须添加如下括号:

find . '(' -name '*.cpp' -o -name '*.h' ')' -exec echo {} ';'

请记住:括号必须用引号引起来或用反斜杠转义,以防止它们被解释为特殊的 shell 字符。

或者使用以下方法将几个扩展组合成一个-regex

find . ! -regex ".*\.\(cpp\|h\)" -exec echo {} \;

答案2

都不是。选项的语法是“错误的”。find按顺序求值。因此,它会求值第一个表达式(-name "*.cpp"),然后遇到一个-o标志。如果第一个表达式为真,find则不会继续求值第二个表达式(-name "*.h" -exec echo {} \;),而是不执行任何操作。您会看到,后面的整个部分-o都是一个表达式。因此,这仅针对与第二个表达式匹配的文件执行。这就是为什么您只看到1.h仅通过第二个表达式的文件的原因。请参阅 find 手册页:

   expr1 -o expr2
          Or; expr2 is not evaluated if expr1 is true.

这有什么用呢?考虑以下:

find /path -exec test_file_for_something {} -print \; -o -name "xyz" -exec ls -l {} \;

在此 find 语句中,文件作为参数提供test_file_for_something。现在,根据该命令返回的代码,第一个表达式为真(然后-print执行并在那里结束)或假(然后-o评估标志后的第二个表达式)。如果那个为真(名称为xyz),则-exec执行。

对于您的问题,您可以使用它将元素分组为一个表达

find . \( -name "*.cpp" -o -name "*.h" \) -exec echo {} \;

答案3

尝试用括号括住您的搜索条件,例如:

find . \( -name "*.cpp" -o -name "*.h" \) -exec echo {} \;

答案4

这就是 find 与其运算符一起工作的方式。

http://linux.die.net/man/1/find部分操作符

运营商

按优先级从高到低的顺序列出: ( expr ) 强制优先级。由于括号是 shell 所特有的,因此通常需要用引号引起来。本手册页中的许多示例都使用反斜杠来达到此目的:'(...)' 而不是 '(...)'。 ! expr 如果 expr 为假,则为真。此字符通常也需要保护,以免被 shell 解释。

-not expr 与 !expr 相同,但不符合 POSIX 标准。expr1 expr2 连续的两个表达式被视为以隐含的“and”连接起来;如果 expr1 为假,则不计算 expr2。expr1 -a expr2 与 expr1 expr2 相同。expr1 -and expr2 与 expr1 expr2 相同,但不符合 POSIX 标准。expr1 -o expr2 或者;如果 expr1 为真,则不计算 expr2。expr1 -or expr2 与 expr1 -o expr2 相同,但不符合 POSIX 标准。expr1 , expr2 列表;始终计算 expr1 和 expr2。expr1 的值被丢弃;列表的值为 expr2 的值。逗号运算符可用于搜索几种不同类型的东西,但只遍历文件系统层次结构一次。-fprintf 操作可用于将各种匹配的项目列出到几个不同的输出文件中。

这应该会给你你想要的结果:

查找 .\(-name '*.cpp'-o-name '*.h' \)-exec echo {} \;

您的命令正在执行此操作(命令不起作用,只是为了向您展示逻辑):

查找。-name'*.cpp'(-o-name'*.h'-exec echo {} \;)

相关内容