使用以下命令,有人可以解释一下结尾大括号 ({}) 和加号 (+) 的确切用途吗?
如果他们被排除在命令之外,命令的运作会有什么不同?
find . -type d -exec chmod 775 {} +
答案1
大括号将被命令的结果替换find
,并且chmod
将在每个命令上运行。 make+
尝试find
运行尽可能少的命令(因此,与, ,chmod 775 file1 file2 file3
相反)。如果没有它们,该命令只会给出错误。这一切都在chmod 755 file1
chmod 755 file2
chmod 755 file3
man find
:
-exec command ;
执行命令;如果返回 0 状态则为 true。以下所有参数
find
被视为命令的参数,直到;
遇到由 ' ' 组成的参数。字符串 '{}
' 会被命令参数中出现的所有地方处理的当前文件名替换,而不仅仅是在单独出现的参数中,如在某些版本中find
。 ……
-exec command {} +
此
-exec
操作的变体对选定的文件运行指定的命令,但命令行是通过在末尾附加每个选定的文件名来构建的;该命令的调用总数将远小于匹配的文件数。 ……
答案2
除了特登的回答之外,
- “显然”必须以分号 ( ) 或加号 ( )
-exec …
结尾。分号是 shell 中的特殊字符(或者至少是我曾经使用过的每个 shell),因此,如果要使用它;
+
find
作为命令的一部分,它必须被转义或引用(\;
,";"
, 或';'
)。 使用 时
-exec … ;
,该{}
字符串可以在命令中出现任意多次,包括零,或两个或更多,在任何位置。 看这 举例说明为什么您可能不想-exec
使用{}
. 具有两个或多个外观是有用的,主要是因为,(至少)在 的某些版本中find
,{}
本身不需要是一个单词;它的开头或结尾可以有其他字符;例如,find . -type f -exec mv {} {}.bak ";"
与
-exec … +
,{}
字符串必须作为 之前的最后一个参数出现+
。像这样的命令find . -name "*.bak" -exec mv {} backup_folder +
结果出现神秘的
find: missing argument to ‘-exec’
错误消息。特定于
cp
和mv
命令的解决方法是find . -name "*.bak" -exec mv -t backup_folder {} +
或者
find . -name "*.bak" -exec mv --target-directory=backup_folder {} +
The
{}
本身必须是一个词;它的开头或结尾不能有其他字符。而且,(至少)在 的某些版本中find
,您可能不会有多个{}
.理智说明:你可以说
寻找 。 -name "*.sh" -type f -executable -exec {}此处可选参数“;”
运行每个脚本。但
寻找 。 -name "*.sh" -type f -executable -exec {} +
运行一您的脚本的名称,所有其他脚本的名称作为参数。这类似于说
./*.sh
作为 shell 命令, except
find
不保证它对其结果进行排序,因此不能保证您可以像运行 一样运行aaa.sh
(按字母顺序排列的第一个文件) 。*.sh
./*.sh
find
初学者可能不太清楚的一个方面是,命令行实际上是一个可执行语句用一种神秘的语言。例如,find . -name "*.sh" -type f -executable -print
方法
for each file if the file’s name matches `*.sh` (i.e., if it ends with `.sh`) then if it is a plain file (i.e., not a directory) then if it is executable (i.e., the appropriate `---x--x--x` bit is set) then print the file’s name end if end if end if end loop
或者,简单地说,
for each file if the file’s name matches `*.sh` AND it is a plain file AND it is executable then print the file’s name end if end loop
有些
-
关键字既是可执行操作又是测试。特别是,对于-exec … ;
;例如,find . -type f -exec grep -q cat {} ";" -print
翻译为
对于每个文件 如果它是一个普通文件(即不是目录) 然后 执行 grep -q cat文件名 如果进程成功(即以状态 0 退出) 然后 打印文件名 万一 万一 结束循环
这将打印包含字符串“”的所有文件的名称
cat
。而且,虽然这是grep
可以单独完成的事情(使用-l
(lower-case ) 选项),但将它与查找包含特定字符串且具有特定大小且由特定所有者拥有的文件L
可能很有用find
并且在一定的时间范围内进行了修改,……。但是,这不适用于
-exec … +
.由于-exec … +
对多个文件执行一个命令,因此将其用作for each file …
循环内的逻辑条件是没有意义的。- 上述情况的另一面是,
find
通常以退出状态 0 退出,除非您给它提供无效的参数或者它遇到无法读取的目录。即使您执行的程序失败(以非零退出状态退出),find
也会以退出状态 0 退出。 除了 如果您执行的程序-exec … +
失败(以非零退出状态退出),find
将以非零退出状态退出。
除了一百万个版本find(1)
并测试find
在几个系统上实际执行的操作之外,
The Open Group 基本规范第 7 期,2013 年版find
提供了一些关于必须做什么、可以做什么和不可以做什么的 信息。