如何使bash扩展变量中的通配符?

Ros*_*can 28 bash scripting expansion

我正在尝试达到与打字相同的效果

mv ./images/*.{pdf,eps,jpg,svg} ./images/junk/  
Run Code Online (Sandbox Code Playgroud)

在命令行,从bash脚本内部.我有:

MYDIR="./images"
OTHERDIR="./images/junk"  
SUFFIXES='{pdf,eps,jpg,svg}'
mv "$MYDIR/"*.$SUFFIXES "$OTHERDIR/"
Run Code Online (Sandbox Code Playgroud)

运行时,它会发出意外错误:

mv: rename ./images/*.{pdf,eps,jpg,svg} to ./images/junk/*.{pdf,eps,jpg,svg}: 
No such file or directory
Run Code Online (Sandbox Code Playgroud)

引用所有这些的正确方法是什么,以便mv实际进行所需的扩展?(是的,有很多文件与模式匹配./images/.)

Pau*_*ce. 29

删除的答案在正确的轨道上.对您的尝试略有修改:

shopt -s extglob
MYDIR="./images"
OTHERDIR="./images/junk"  
SUFFIXES='@(pdf|eps|jpg|svg)'
mv "$MYDIR/"*.$SUFFIXES "$OTHERDIR/"
Run Code Online (Sandbox Code Playgroud)

支撑扩展在变量扩展之前完成,但变量扩展在路径名扩展之前完成.因此,当变量在原始文件中展开时,大括号仍然是大括号,但是当变量包含路径名元素时,它们在路径名扩展完成后已经展开.

  • +1,整洁的把戏,不知道`@()`,我学到了新东西.只是在联机帮助页中查找,因为有人想知道有`?()`模式,`*()`模式,`+()`模式,`@()`模式和`!()`模式.如果启用`extglob`,则全部可用. (5认同)
  • @RossDuncan,我建议将http://mywiki.wooledge.org/BashParser作为开始的地方,以便对Shell的执行模型所涉及的各个阶段以及它们发生的顺序进行很好的参考。 (2认同)

fal*_*tro 8

您需要评估该行才能使其正常工作,如下所示:

MYDIR="./images"
OTHERDIR="./images/junk"  
SUFFIXES='{pdf,eps,jpg,svg}'
eval "mv \"$MYDIR\"/*.$SUFFIXES \"$OTHERDIR/\""
Run Code Online (Sandbox Code Playgroud)

现在,这有问题,特别是如果你不信任$SUFFIXES,它可能包含注入攻击,但对于这个简单的情况它应该没问题.

如果您对其他解决方案持开放态度,您可能希望尝试使用findxargs.


Dag*_*ang 5

你可以写一个函数:

function expand { for arg in "$@"; do [[ -f $arg ]] && echo $arg; done }

然后用你想要扩展的内容来调用它:

expand "$MYDIR/"*.$SUFFIXES

如果您愿意,也可以将其设为脚本 Expand.sh。

  • 是的,答案中的“echo”而不是“expand”会给出每个匹配项,而不仅仅是文件。在一般情况下,如果您只想扩展通配符,并且希望将结果存储在数组中,只需使用:`array=($(echo /path/to/files.*))`。或者没有路径:`array=($(cd /some/path && echo file-*.jpg))`。当然要小心文件名中的特殊字符。 (2认同)