Bash:由于不需要的转义,脚本中的大括号扩展无法工作
我想在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} 执行此脚本时,不会删除文
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