使用花括号参数列表多次执行命令

时间:2012-12-20 12:03:13

标签: bash shell command-line command-line-arguments brace-expansion

当我需要使用不同的参数多次运行命令时,我使用了这种方法(没有完全理解它):

touch {a,b,c}

相当于:

touch a
touch b
touch c

我认为可以通过以下循环完成同样的事情:

for file in {a,b,c}; do touch $file; done

但是,我偶然发现了一个不起作用的案例:

pear channel-discover {"pear.phpunit.de","pear.symfony-project.com"}

我有几个问题:

  1. 第一个例子中发生了什么的名称以及到底发生了什么?
  2. 将此方法用于简单事物而不是for-in循环是否更好?
  3. 为什么pear命令不能那样工作?命令脚本应该实现一些处理这些参数的技术,还是shell负责这个?

3 个答案:

答案 0 :(得分:12)

这称为Brace Expansion,它扩展为给定字符串的空格分隔列表。

所以touch {a,b,c}等同于

touch a b c

虽然touch {a,b,c}x等同于:

touch ax bx cx

pear命令基本上可以运行:

pear channel-discover pear.phpunit.de pear.symfony-project.com

可能不是您的预期。如果你想为每个字符串运行一次命令,请使用for循环(它回答你的第二个问题),或者使用大括号扩展和xargs的组合。

答案 1 :(得分:6)

问题是与您的期望相反,支撑扩展

touch {a,b,c}

相当于

touch a b c   # NOT 3 separate invocations.

(使用echo {a,b,c}进行验证)。 pear channel-discover似乎不接受两个 args。您可能会看到与

相同的错误
pear channel-discover pear.phpunit.de pear.symfony-project.com

答案 2 :(得分:0)

嗯,你有两个选择:

for i in "pear.phpunit.de" "pear.symfony-project.com"
do
  pear channel-discover "$i"
done

或单行(但调用xargs而不是使用bash内部):

echo "pear.phpunit.de" "pear.symfony-project.com" | xargs -n1 pear channel-discover

前者当然更容易被人阅读,时间效率基本相同。