如何在 find 命令的 -exec 中使用两个 bash 命令?

Luc*_*c M 33 bash find

是否可以在command-exec部分使用 2 个命令find

我试过这样的事情:

find . -name "*" -exec  chgrp -v new_group {}  ; chmod -v 770 {}  \;
Run Code Online (Sandbox Code Playgroud)

我得到:

查找:缺少 -exec
chmod 的参数:无法访问 {}:没有这样的文件或目录
chmod:无法访问;:没有这样的文件或目录

roz*_*acz 49

至于find命令,您也可以-exec连续添加更多命令:

find . -name "*" -exec chgrp -v new_group '{}' \; -exec chmod -v 770 '{}' \;
Run Code Online (Sandbox Code Playgroud)

请注意,此命令在其结果中等效于使用

chgrp -v new_group 文件&& chmod -v 770 文件

在每个文件上。

所有find的参数,如-name-exec-size等等,其实都是测试find将继续由一个只要运行它们作为一个整个链条迄今已评估为。因此,当前一个-exec命令返回true(即命令的退出状态)时,才会执行每个连续命令。但也理解逻辑运算符,例如or ( ) 和not ( )。因此,无论先前的结果如何,要使用一系列测试,需要使用以下内容:0find-o!-exec

find . -name "*" \( -exec chgrp -v new_group {} \; -o -true \) -exec chmod -v 770 {} \; 
Run Code Online (Sandbox Code Playgroud)

  • +1:是的,这是最优雅的方式。如果您能解释为什么使用`'{}'`(大括号周围的撇号),请访问:http://unix.stackexchange.com/q/8647/4485 (4认同)
  • 引号对于名称中有空格的文件很重要。 (2认同)

gle*_*man 18

find . -name "*" -exec sh -c 'chgrp -v new_group "$0" ; chmod -v 770 "$0"' {} \;
Run Code Online (Sandbox Code Playgroud)


Gil*_*il' 16

您的命令首先被 shell 解析为两个由 a 分隔的命令;,这相当于换行:

find . -name "*" -exec chgrp -v new_group {}
chmod -v 770 {} \;
Run Code Online (Sandbox Code Playgroud)

如果要运行 shell 命令,请使用以下命令显式调用 shell bash -c(或者sh -c如果您不关心 shell 是专门的 bash):

find . -name "*" -exec sh -c 'chgrp -v new_group "$0"; chmod -v 770 "$0"' {} \;
Run Code Online (Sandbox Code Playgroud)

请注意{}用作 shell 的参数;它是第零个参数(通常是 shell 或脚本的名称,但这在这里无关紧要),因此引用为"$0".

您可以一次将多个文件名传递给 shell,并让 shell 遍历它们,这样会更快。在这里,我_作为脚本名称传递,以下参数是文件名,它for x( 的快捷方式for x in "$@")迭代。

find . -name "*" -exec sh -c 'for x; do chgrp -v new_group "$x"; chmod -v 770 "$x"; done' _ {} +
Run Code Online (Sandbox Code Playgroud)

请注意,由于 bash 4 或 zsh,您根本不需要在这里找到。在 bash 中,运行shopt -s globstar(将其放入您的~/.bashrc)以激活**/代表递归目录 glob。(在 zsh 中,它一直处于活动状态。)然后

chgrp -v new_group -- **/*; chmod -v 770 -- **/*
Run Code Online (Sandbox Code Playgroud)

或者如果您希望按顺序迭代文件

for x in **/*; do
  chgrp -v new_group -- "$x"
  chmod -v 770 -- "$x"
done
Run Code Online (Sandbox Code Playgroud)

与该find命令的一个区别是 shell 忽略点文件(名称以 a 开头的文件.)。要包含它们,在 bash 中,首先设置GLOBIGNORE=.:..; 在 zsh 中,**/*(D)用作 glob 模式。