10

我想在 bash 脚本中做这样的事情。我正在使用bash 4.1.10.

# rm -rf /some/path/{folder1,folder2,folder3}

从外壳本身很好地工作(并且如预期的那样)。它删除了 3 个所需的文件夹,而其他所有文件夹都保持不变。

当我把它放到脚本中时,会发生一些不想要的事情。例如,我的脚本:

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

当我执行此脚本时,不会删除文件夹。

我认为这是由于发生了一些不需要的引用。使用以下脚本输出#!/bin/bash -x

rm -rf '/some/path/{folder1,folder2,folder3}'

'由于分数,这当然不能成功。

我怎样才能让这个在我的脚本中工作?

4

9 回答 9

12

根据手册页

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

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

eval "rm -rf /some/path/{$VAR}"
于 2011-07-01T14:13:45.963 回答
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
于 2011-07-01T14:55:00.463 回答
2

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

xargs -d , -I {} rm -rf /some/path/{} <<< "$VAR"
于 2011-07-01T14:12:40.157 回答
2

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

#!/bin/bash
set -x
VAR=`echo /some/path/{folder1,folder2,folder3}`
rm -rf $VAR
于 2012-05-17T22:33:57.983 回答
1

您需要启用大括号扩展标志:

#!/bin/bash
set -B
for i in /some/path/{folder1,folder2,folder3}
do
  rm -rf "$i"
done
于 2013-01-25T18:16:52.710 回答
0
#!/bin/bash
set -x
VAR="folder1,folder2,folder3"
eval "rm -rf /some/path/{$VAR}"

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

最近的 bash 有 globstar 选项。这可能会在未来派上用场

shopt -s globstar
rm -rfvi some/**/folder?
于 2011-07-01T14:12:28.400 回答
0

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

eval "rm -rf /some/path/{$VAR}"
于 2011-07-01T14:12:47.853 回答
0

您可以使用的另一个技巧(而不是危险的eval)只是echo在子shell 中。这有效,例如:

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中发生大括号扩展,将空格分隔的字符串列表放入变量中。

于 2013-02-08T05:42:31.353 回答
-1

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

于 2011-07-01T14:13:49.580 回答