find 命令中“{}”和{} 之间的区别?

tar*_*yte 18 linux bash command-line find syntax

文档中,我看到了两种用法:

find . -type f -exec file '{}' \;

find repo/ -exec test -d {}/.svn -o -d {}/.git -o -d {}/CVS ; \
Run Code Online (Sandbox Code Playgroud)

Ste*_*ven 24

对于bash外壳,'{}'{}是可以互换的。并非所有外壳都如此(例如fish)。

将参数放在单引号中明确表示应该将大括号发送到find. 根据用法,bash shell 有时会替换大括号的内容。

如下所示,bash 不会替换空括号,它们会传递给命令。对于find命令,没关系。

$ echo {}
{}

$ echo {1}
{1}

$ echo {1,3}
1 3

$ echo '{1,3}'
{1,3}
Run Code Online (Sandbox Code Playgroud)

  • 与 bash 无关。和鱼有关系。 (4认同)

Ant*_*gan 9

对于大多数用户(尤其是使用 POSIX shell 的用户),没有区别。

根据 GNU 手册页的示例部分find

请注意,大括号用单引号括起来,以防止它们被解释为 shell 脚本标点符号。

我认为 GNU 手册页的作者在谨慎方面犯了错误,但我注意到并非他们手册页中的所有示例都引用了大括号。这些来自官方 GNU find 文档的示例也省略了引用。

POSIX / Single UNIX Specification示例中,当与选项一起使用时,大括号没有被引用-exec

对于 POSIX shell,参数扩展 仅在大括号内包含特殊参数时发生 - 而不是空大括号

Bash shell 包含大括号扩展作为(不可移植的)功能,但只有在大括号中包含逗号或点时,才会扩展此类模式。Bash 还使用大括号进行命令分组,但除非大括号内实际上一组命令,否则不会发生这种情况。

最后,我试图运行find -exec ls -l {} \;shdash并且tcsh但这些炮弹扩大{}到其他任何东西。正如其他人指出的那样,fishshell 进行了{}特殊处理,但这不是 POSIX shell(其创建者和用户认为这是一个优势)。它没有伤害引用括号谁不使用鱼外壳不应该感到内疚忽略他们,但懒惰的打字员。


jll*_*gre 9

几乎所有的 shell 解释器都可用,'{}'和之间绝对没有区别{}

单引号通常用于保护嵌入的字符串不被其他东西替换,例如:

  • 'a b' 是一个三个字符的参数,没有引号,这将是两个单字符参数
  • '$b' 字面上是美元符号,后跟字母 b,不带引号,即 b 变量包含的任何内容,如果未设置则可能什么都没有
  • '!!' 是不带引号的感叹号,并且在一些交互式 shell 中,它们会扩展到历史记录中的最后一个命令
  • '*' 是一个字面上的星号,不加引号它将被当前目录中的非隐藏文件名列表替换。

由于 POSIX 标准和主流 shell ( sh(Bourne), ksh, bash, ash, dash, zsh, csh, tcsh){}都没有扩展到其他东西,因此不需要引号。

但是,有一个名为 的奇特外壳,fish它恰好扩展{}为空字符串,例如:

> ps -p %self
  PID TTY          TIME CMD
 5247 pts/1    00:00:00 fish
> echo a {} b '{}'
a  b {}
Run Code Online (Sandbox Code Playgroud)

这可能是 GNUfind文档建议{}使用引号或反斜杠来防止解释的原因。


use*_*284 6

这取决于您的 shell 的语法。如有疑问,请回声!

运行这个

echo '{}'
Run Code Online (Sandbox Code Playgroud)

和这个。

echo {}
Run Code Online (Sandbox Code Playgroud)

如果它们产生相同的输出,那么您的 shell 的答案是肯定的。正如其他人所指出的那样,至少在 bash 中是肯定的,而在fish 中则不是。输出是您应该查阅给定命令的联机帮助页的内容。


如果您想方便一些,您甚至echo可以为整个命令行添加前缀,以查看实际命令及其所有参数,您的 shell 将实际调用这些命令。但请注意,包含命令和参数的列表是一个真正的字符串数组,每个字符串可能为空或带有空格,但 echo 将其打印为空格分隔的列表。

可以通过这个稍微详细一点的 echo 命令(显示 guillemet 引用的参数)进行验证,

#!/bin/sh
for a in "$@"; do
    printf '«%s» ' "$a"
done
echo ''
Run Code Online (Sandbox Code Playgroud)

在命令行输入这个,

find 'My Documents and Settings' -type f -exec file {} \;
Run Code Online (Sandbox Code Playgroud)

这意味着 bash:

«find» «My Documents and Settings» «-type» «f» «-exec» «file» «{}» «;»
Run Code Online (Sandbox Code Playgroud)

这在鱼中:

«find» «My Documents and Settings» «-type» «f» «-exec» «file» «» «;»
Run Code Online (Sandbox Code Playgroud)

作为一般性建议,引用永远不会有什么坏处。