使用大括号 {} 作为命令及其选项的参数

Nik*_*mbt 13 shell bash

例子

我最近发现了使用成对的大括号的例子,在左大括号和右大括号{}之间没有任何东西,作为命令的参数,甚至是它们的选项:

cat foo | xargs -I{} echo {}

find . -size 0 -exec rm -i {} \;

无文档

我的问题是我在GNU Bash 手册中找不到描述{}在上述示例中使用的文档。

我不认为它是参数扩展,因为在参数扩展中,美元符号必须位于括号前,如${}.

它也不能是大括号扩展,因为它采用{x..y[..incr]}、 wherexy不是可选的形式。

它也不能是命令分组,因为{}用作参数。

问题

  1. {}一般来说,一对封闭的大括号作为任何接受它的命令的参数意味着什么?

  2. 在哪里可以找到描述{}as 参数用法的文档?

tin*_*ink 18

这些花括号被 bash 单独留下;它们分别属于findxargs,并在它们的手册页中进行了描述。

man find

-exec 命令 ;

执行命令;如果返回 0 状态,则为 true。find 的所有以下参数都被视为命令的参数,直到;遇到由 of 组成的参数。该字符串{}被当前正在处理的文件名替换,它出现在命令的参数中的任何地方,而不仅仅是在单独存在的参数中,如在某些版本的find. 这两种结构都可能需要转义(使用 a \)或引用以防止它们被 shell 扩展。有关使用该-exec选项的示例,请参阅示例部分。指定的 命令对每个匹配的文件运行一次。该命令在起始目录中执行。围绕-exec 动作的使用存在不可避免的安全问题;您应该改用该-execdir选项。

-exec 命令 {} +

这个-exec动作的变体在选定的文件上运行指定的命令,但命令行是通过在末尾附加每个选定的文件名来构建的;命令的总调用次数将远小于匹配文件的数量。命令行的构建方式与xargs构建其命令行的方式大致相同。命令中只{}允许一个实例。该命令在起始目录中执行。如果find遇到错误,这有时会导致立即退出,因此一些挂起的命令可能根本无法运行。这个变体-exec总是返回真。

-execdir 命令 ;

-execdir 命令 {} +

类似 -exec,但指定的命令是从包含匹配文件的子目录运行的,该目录通常不是您开始查找的目录。这是一种更安全的调用命令的方法,因为它在解析匹配文件的路径期间避免了竞争条件。与 -exec action 一样,+ of的 形式 -execdir 将构建一个命令行来处理多个匹配的文件,但任何给定的命令调用只会列出存在于同一子目录中的文件。如果您使用此选项,您必须确保您的$PATH环境变量不引用.; 否则,攻击者可以通过在您将运行的目录中留下一个适当命名的文件来运行他们喜欢的任何命令-execdir。这同样适用于具有$PATH空或不是绝对目录名称的条目。如果find遇到错误,这有时会导致立即退出,因此一些挂起的命令可能根本无法运行。操作的结果取决于使用的是变体+还是;变体; -execdir command {} +始终返回 true,而-execdir command {} ;仅在command返回 0时返回 true 。

man xargs

-I 替换-str

用从标准输入读取的名称替换初始参数中出现的replace-str。此外,未加引号的空格不会终止输入项;相反,分隔符是换行符。暗示-x-L 1

-i[替换字符串],--replace[=替换字符串]

此选项的代名词-I顶替-STR如果更换-STR指定的。如果缺少replace-str参数,则效果与-I{}. 此选项已弃用;使用-I来代替。

编辑:这里为什么bash 忽略那些花括号:

man bash

{ 列表; }

list 只是在当前 shell 环境中执行。 列表必须以换行符或分号结束。这称为组命令。返回状态是列表的退出状态。请注意,与元字符( and ) 不同{}是保留字,必须出现在允许识别保留字的地方。由于它们不会导致断字,因此它们必须通过空格或其他 shell 元字符与列表分开。

为了强调:列表必须以换行符或分号结束

  • @NikoGambt 好吧,{} 对 xargs 没有任何意义,除了作为 -i 的默认值,已弃用。我不确定除此之外还需要什么解释。在您发布的示例中,它也可能是`xargs -Iab echo ab`;这纯粹是一个随意的选择。 (5认同)