【问题标题】:brace expansion command not recognized大括号扩展命令无法识别
【发布时间】:2014-09-23 15:46:09
【问题描述】:

如何使用大括号扩展(或其他简单方法)重复 shell 命令,为命令的每次迭代调整某些参数?这是我想做的一个简单示例(但命令更冗长): cp a b; cp a c;

显然,如果我在终端中输入它就可以了。但我希望能够以更紧凑的方式生成它。我尝试使用 bash 大括号扩展,但它给了我一个找不到命令的错误:

~/test $ ls
a
~/test $ cp\ a\ {b,c}\;
cp a b;: command not found
~/test $ 

使用反引号也不起作用。

~/test $ `cp\ a\ {b,c}\;`
cp a b;: command not found

【问题讨论】:

  • 您正在构建一个cp a b; 的字符串。那不是命令。那是一个字符串。尝试输入“cp a b;”在你的外壳上,看看会发生什么。没有eval,您将无法在此处执行您想做的事情。 echo b c | xargs cp a 应该在这里做你想做的事情,但不知道 真实 的情况是什么,我无法提供更好的解决方案。
  • @etan 好建议。一个更明确的写法是for f in b c; do cp a $f; done,但这只是风格问题。
  • eval cp\ a\ {b,c}\; 似乎有效。一方面,反引号和 $() 和另一方面的 eval 到底有什么区别?
  • shell 对输入行的每个单词应用各种类型的扩展,以评估命令的最终参数。当该命令为eval 时,生成的参数将经历整个过程再次,这次将第一个参数作为最终执行的命令。
  • @mike,使用此处给出的反引号读取 cp 命令的标准输出并尝试将该标准输出作为另一个命令本身运行,因此在 cp 将内容发送到标准错误的常见情况下根本没有效果只有标准输出,没有任何东西。

标签: bash shell backticks brace-expansion


【解决方案1】:

以正确和安全的方式执行此操作并不像您希望的那样简洁:

for arg in b c; do cp a "$arg"; done

引号很重要——否则,名为filename with a space 的文件将被转换为四个单独的参数,filenamewithaspace。 (如果您实际上只处理 bc,那不是问题,但养成让您以后陷入困境的习惯并不是一个好习惯。


您的问题和 cmets 假设使用 eval 来处理大括号扩展的结果,但这有点邪恶:

eval "cp a "{b,c}";"

这样做的问题是,虽然它适用于非常简单的参数,但它会以令人惊讶和意想不到的方式处理不那么简单的参数(特别是包含 shell 语法的文件名)。因此,这是非常糟糕的做法。


关于反引号 --

`cp a b c`

完全一样

cp a b c

...除了它还从cp 的标准输出中读取,将 cp 的输出替换到结果命令中,然后也运行该命令。

所以,

echo `cp a b c`

首先运行cp a b c,读取输出——它是空的,因为即使有错误,它也会写入stderr,而不是stdout,然后运行

echo

...没有参数。如果 cp did 向其标准输出发送了某些内容,则该字符串将被解析为参数,并且这些参数将传递给 echo

【讨论】:

  • 感谢您的详尽解释。非常有帮助。没有我希望的那么紧凑,但它确实有效。
  • 但是,我仍然不明白为什么反引号不起作用。根据您的解释(并假设它首先进行大括号扩展),`cp\ a\ {b,c}\;`(带反引号)应该run cp a b; a c;(扩展且没有反引号)然后,因为没有地方可以替代它,什么都不做?但相反,它给了我一个错误。也许 bash 不会在反引号内进行大括号扩展?
  • 另外,顺便说一句,我试图运行cp a b; cp a c; 而不是cp a b c,正如你在反引号解释中所显示的那样。不知道你是不是故意改的。
  • @mike,`cp\ a\ {b,c}\;`cp\ a\ {b,c}\; 完全相同——除了添加一个额外的步骤,命令的输出再次作为另一个命令运行之外,反引号没有任何区别。
  • 好吧——它做了大括号扩展,但它扩展为一个字符串,其中包含空格作为数据,而不是语法(因为当你写 \ 时,这正是你告诉 shell 的做,只有eval 或等效的可以将数据转换回语法)。这意味着它正在尝试查找并运行一个名为 /bin/cp a b c; 之类的文件,其名称中包含空格和分号,而不是 /bin/cp
猜你喜欢
  • 1970-01-01
  • 2021-07-15
  • 1970-01-01
  • 2017-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多