Bash:由于不需要的转义,脚本中的大括号扩展无法工作

Bash:由于不需要的转义,脚本中的大括号扩展无法工作,bash,escaping,brace-expansion,Bash,Escaping,Brace Expansion,我想在bash脚本中执行类似的操作。我正在使用bash4.1.10 # rm -rf /some/path/{folder1,folder2,folder3} 从shell本身就可以很好地工作(正如预期的那样)。它删除了3个所需的文件夹,其他所有文件夹保持不变 当我把它写进脚本时,一些不想要的事情发生了。例如,我的脚本: #!/bin/bash set -x VAR="folder1,folder2,folder3" rm -rf /some/path/{$VAR} 执行此脚本时,不会删除文

我想在bash脚本中执行类似的操作。我正在使用
bash4.1.10

# rm -rf /some/path/{folder1,folder2,folder3}
从shell本身就可以很好地工作(正如预期的那样)。它删除了3个所需的文件夹,其他所有文件夹保持不变

当我把它写进脚本时,一些不想要的事情发生了。例如,我的脚本:

#!/bin/bash
set -x
VAR="folder1,folder2,folder3"
rm -rf /some/path/{$VAR}
执行此脚本时,不会删除文件夹

我认为这是由于一些不必要的引用正在发生。使用
#从脚本输出/bin/bash-x

rm -rf '/some/path/{folder1,folder2,folder3}'
当然,由于
标记,该操作无法成功

如何在我的脚本中实现这一点

#!/bin/bash
set -x
VAR="folder1,folder2,folder3"
eval "rm -rf /some/path/{$VAR}"

编辑其余部分仅供参考。我尽量提供信息,但不要罗嗦:

最近的狂欢节有globstar选项。这可能在将来派上用场

shopt -s globstar
rm -rfvi some/**/folder?

不,这是因为支架展开发生在参数展开之前。找到另一种方法,例如使用
xargs

xargs -d , -I {} rm -rf /some/path/{} <<< "$VAR"
xargs-d,-I{}rm-rf/some/path/{}问题不是在脚本模式下发生了一些不必要的引用,而是您将文件夹名称放入了一个变量中,并且在大括号展开后展开了变量内容。
如果你真的想这样做,你必须使用
eval

eval "rm -rf /some/path/{$VAR}"
根据:

展开顺序为:大括号展开、平铺展开、参数展开、变量和算术展开以及命令替换(以从左到右的方式完成)、分词和路径名展开

因此,要解决这个问题,请添加另一个扩展级别:

eval "rm -rf /some/path/{$VAR}"

{$VAR}
替换为
${VAR}
:-)

既然您正在编写脚本,就没有理由使用
eval
技巧编写难以维护的代码

VAR="f1,f2,f3"
IFS=,
set -- $VAR
for f; do
  rm -r "/path/to/$f"
done


如果可以重新排列代码,那么可以在bash中使用
echo
和命令替换。 大概是这样的:

#!/bin/bash
set -x
VAR=`echo /some/path/{folder1,folder2,folder3}`
rm -rf $VAR

您需要启用braceexpand标志:

#!/bin/bash
set -B
for i in /some/path/{folder1,folder2,folder3}
do
  rm -rf "$i"
done
您可以使用的另一个技巧(而不是危险的
eval
)就是在子shell中使用普通的
echo
。例如,这是可行的:

paths=`echo /some/path/{folder1,folder2,folder3}`
echo rm -rf $paths
产出:

rm -rf /some/path/folder1 /some/path/folder2 /some/path/folder3
如所愿。(删除第二行中的“echo”,使其实际执行
rm



关键的一点是bash在参数扩展之前进行大括号扩展,因此您永远不希望将逗号分隔的列表(是否由大括号包围)放入变量中——如果这样做,则必须求助于
eval
。但是,通过在赋值之前在子shell中进行大括号扩展,可以将空格分隔的字符串列表放入变量。

您是绝对希望使用{}-expansion,还是等效的替代方法确定?当然。。我只想在后台的一个具体子shell中删除一系列子文件夹名称,这意味着更具体:rm-rf/some/path/{folder1,folder2,folder3}&不是在每个子文件夹上运行的循环,因为这样做会增加文件服务器的负载我希望生成有关$VAR内容的大括号而不是$VARi的大括号扩展我的具体情况我没有folder1、folder2、folder3,但有完整的不同名称。把这个特殊的例子放在这里,这会奏效的。@Roland:我真的提到了
globstar
,我想你还不知道。你确实注意到了答案(你知道,第一部分)?似乎对我不起作用。(请注意,
“/some/path/{folder1,folder2,folder3}”
字符串存储在一个变量中;如果您在shell中按字面意思输入上述内容,它将起作用,因为shell进行扩展,但它在脚本中没有用处。)但如果您知道要进行大括号扩展的实际文字列表,那么它将起作用:
for i in${prefix}{fixed,list,of,literal,strings}${suffix}
将循环5个字符串,其中
${prefix}
${suffix}
正确替换。修复了答案。您需要设置-B/braceexpand with set,或将其作为bash参数提供:)不,仍然不起作用。我认为您不理解这个问题:假设您有一个变量,如
VAR=“/tmp/{folder1,folder2,folder3}”
。现在您想要创建(比如说)相应的目录,使用$VAR。您是如何做到的?(如果您在VAR中没有它,可以直接键入它,那么一切都很好,正如我在上面的第二条评论中所说的。)
rm -rf /some/path/folder1 /some/path/folder2 /some/path/folder3