我得到了一个我不理解的 unix‘find’命令的结果。
使用 MacOS 上的终端(我相信它是符合 POSIX 标准的操作系统)运行此 shell 脚本:
#!/bin/bash
#
echo "version 1"
find . -iname "*tif" -o -iname "*foo"
#
echo "version 2"
find . -iname "*tif" -o -iname "*foo" -print
我得到的结果:
version 1
./file1.tif
./file2.tif
./file3.tif
version 2
%
我希望获得相同的输出。 为什么使用“或”进行“打印”会抑制输出并导致找不到任何内容?
答案1
此命令:
find . -iname "*tif" -o -iname "*foo"
相当于:
find . \( -iname "*tif" -o -iname "*foo" \) -print
换句话说,隐式表达式-print
不是无意识地添加到末尾的。它是在将显式表达式作为一个整体处理后添加到末尾的。这在POSIX 规范find
:
如果不存在表达式,
-exec
、-ok
或( given_expression ) -print
在 shell 中,您需要转义或引用每个括号,因此在我上面的代码中\(
是 和\)
。还请注意,您的实现find
可能会将某些内容(例如-printf
)添加到抑制隐式 的初始项列表中-print
。
您的其他命令是:
find . -iname "*tif" -o -iname "*foo" -print
它相当于:
find . -iname "*tif" -o \( -iname "*foo" -a -print \)
括号的位置暗示了这样一个事实-a
(即使你省略它),其约束力“比”更强-o
。
现在,手册的以下片段是相关的:
expression -o expression
主元交替;或运算符。如果第一个表达式为真,则不应计算第二个表达式。
在我们的例子中,第二个表达式是括号的全部内容。如果给定文件的-iname "*tif"
求值结果为真,则-iname "*foo" -a -print
根本不求值。
这种“完全”的后果有些令人惊讶,在以下命令中体现出来,其中出现了两次-iname "*tif"
:
find . -iname "*tif" -o -iname "*tif" -print
此命令永远不会-print
。对于任何文件:
- 要么第一个
-iname "*tif"
为真,则之后的所有内容-o
都不会被评估; - 或者第一个
-iname "*tif"
为假,因此第二个-iname "*tif"
被评估并且也是假,所以-print
不被评估。
find . expression1 -o expression2 -print
-print
当且仅当expression1
求值结果为假并且求值结果为真时,才会为路径名expression2
。
类似问题:将多个 find 命令合并为一个。