4

我的问题与如何使用 cp 从不同目录复制多个文件非常相似

我不想使用显式循环。这是我所做的:

$ FILES_TOOLS="fastboot,fastboot-HW.sh"
$ cp $HOME/tools/{$FILES_TOOLS} $TOP_DIR/removeme
cp: cannot stat `/home/johndoe/tools/{fastboot,fastboot-HW.sh}': No such file or directory

文件存在且目标有效,因为:

$ cp $HOME/tools/{fastboot,fastboot-HW.sh} $TOP_DIR/removeme
$ echo $?
0
  • 我试图从 FILES_TOOLS 中删除双引号,但不走运。
  • 我试图引用和双引号 {...},没有运气
  • 我试图反斜杠括号,没有运气
  • 我想这是外壳扩展实际发生时的问题。
4

3 回答 3

2

这个答案仅限于 bash。

预先添加一个echo以查看您的cp命令变成了什么:

echo cp $HOME/tools/{$FILES_TOOLS} $TOP_DIR/removeme

您必须在子外壳中插入一个eval才能使其工作:

cp $( eval echo $HOME/tools/{$FILES_TOOLS} ) $TOP_DIR/removeme
于 2013-02-08T22:24:34.797 回答
1

我想这是外壳扩展实际发生时的问题。

是的。不同的 shell 对于与变量扩展相关的大括号扩展有不同的规则。您的方式适用于 ksh,但不适用于 zsh 或 bash。{1..$n}适用于 ksh 和 zsh 但不适用于 bash。在 bash 中,变量扩展总是发生在大括号扩展之后。

在 bash 中你最接近这个的是eval.

于 2013-02-08T22:23:18.813 回答
1

只要大括号的内容是文字,您就可以使用大括号扩展来使用要复制的文件的完整路径名填充数组,然后在cp命令中展开数组的内容。

$ FILES_TOOLS=( $HOME/tools/{fastboot,fastboot-HW.sh} )
$ cp "${FILES_TOOLS[@]}" $TOP_DIR/removeme

更新:我意识到你可能有理由在变量中单独使用基本名称。这是另一个基于数组的解决方案,可让您在数组的每个元素前加上路径,同样无需显式循环:

$ FILES_TOOLS=( fastboot fastboot-HW.sh )
$ cp "${FILES_TOOLS[@]/#/$HOME/tools/}" $TOP_DIR/removeme

在这种情况下,您使用模式替换运算符将每个数组元素开头的空字符串替换为目录名称。

于 2013-02-09T00:04:04.417 回答