Bash:由于不必要的转义,脚本中的扩展功能无法正常工作

时间:2011-07-01 14:06:25

标签: bash escaping brace-expansion

我想在bash脚本中做这样的事情。我正在使用bash 4.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}'

由于'标记,当然无法成功。

如何在我的脚本中使用它?

9 个答案:

答案 0 :(得分:11)

根据the man page

  

扩展的顺序是:大括号扩展,波浪扩展,参数,变量和算术扩展以及命令替换(以从左到右的方式完成),单词拆分和路径名扩展。

为了解决这个问题,请添加另一个扩展级别:

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

答案 1 :(得分:5)

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

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

VAR=( f1 f2 f3 )
for f in "${VAR[@]}"; do 
  rm -r "/path/to/$f"
done

答案 2 :(得分:2)

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

xargs -d , -I {} rm -rf /some/path/{} <<< "$VAR"

答案 3 :(得分:2)

如果您的代码可以重新排列,您可以在bash中使用echo和命令替换。 像这样:

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

答案 4 :(得分:1)

您需要启用braceexpand标志:

#!/bin/bash
set -B
for i in /some/path/{folder1,folder2,folder3}
do
  rm -rf "$i"
done

答案 5 :(得分:0)

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

修改其余内容仅供参考。我试着提供信息,但不要罗嗦:_)

最近的bashes有globstar选项。这可能在将来派上用场了

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

答案 6 :(得分:0)

问题不在于在脚本模式下发生了一些不需要的引用,而是您将文件夹名称放入变量中,并且在大括号扩展后扩展变量内容完了。
如果你真的想这样做,你必须使用eval

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

答案 7 :(得分:0)

你可以使用的另一个技巧(而不是危险的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 中进行大括号扩展,将空格分隔的字符串列表放入变量中。

答案 8 :(得分:-1)

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