find -exec 和通过 xargs 进行管道传输之间的不同行为

find -exec 和通过 xargs 进行管道传输之间的不同行为

我想chmod go+w在包括隐藏文件的特定文件夹中递归运行,我首先尝试

find . -name ".*" -o -name "*" -exec chmod go+w {} \;

但我发现它不会影响隐藏文件。为了检查自己,我跑了

find . -name ".*" -o -name "*"

并列出了隐藏文件。我还注意到,如果我排除该-o -name "*"部分,它将 chmod 隐藏文件(但当然排除非隐藏文件)。我最后一次尝试是使用 xargs 代替

find . -name ".*" -o -name "*" | xargs chmod go+w

最终按预期工作。我在第一个片段中做错了什么?

红帽企业 Linux 服务器版本 6.8(圣地亚哥)

GNU bash,版本 4.3.42(1)-release (x86_64-unknown-linux-gnu)

答案1

解决方案是将两个名称测试用括号绑定在一起。

为了说明这一点,让我们考虑一个包含三个常规文件的目录:

$ ls -a
.  ..  .hidden1  .hidden2  not_hidden

现在,让我们看看原来的命令:

$ find . -name ".*" -o -name "*" -exec echo Found {} \;
Found ./not_hidden

仅找到非隐藏文件。

接下来,让我们添加括号将两个名称测试分组在一起:

$ find . \( -name ".*" -o -name "*" \) -exec echo Found {} \;
Found .
Found ./not_hidden
Found ./.hidden1
Found ./.hidden2

所有文件都找到了。

解决方案是使用括号。

更多细节

-name "*"在原始命令中,和 之间没有运算符-exec ... \;。因此,find假定默认运算符是逻辑与。因为逻辑与比逻辑或 ( -o) 绑定更紧密,这意味着该命令被解释为:

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

这意味着exec仅当第一个name条件不匹配时才运行。

欲了解更多信息,请参阅运营商中的部分man find

没有的话会发生什么-exec

让我们尝试使用一个简单的-print

$ find . -name ".*" -o -name "*" -print
./not_hidden

正如您所看到的,与上面的隐式逻辑“and”-print绑定在一起。-name "*"

但是,考虑一下在没有指定任何操作的情况下会发生什么:

$ find . -name ".*" -o -name "*"
.
./not_hidden
./.hidden1
./.hidden2

到这里,所有的文件都找到了。原因是,在这个版本中-o仅有的操作员。

相关内容