该外壳扩展*
仅当外壳未引述任何引用停止扩张。
同样,括号扩展名也需要取消引用才能被外壳扩展。
这项工作(让我们使用echo来查看shell的功能):
$ echo *.{ext1,ext2}
a.ext1 b.ext1 a.ext2 b.ext2
即使有一些其他名称的文件:
$ touch {a,b}.{ext1,ext2} {c,d}.{ext3,ext4} none
ls
a.ext1 a.ext2 b.ext1 b.ext2 c.ext3 c.ext4 d.ext3 d.ext4 none
$ echo *.{ext1,ext2}
a.ext1 b.ext1 a.ext2 b.ext2
为什么行得通?
重要的是我们了解为什么会起作用。这是因为扩展的顺序。首先是“括号扩展”,然后是(最后一个)“路径名扩展”(aka glob-expansion)。
Brace --> Parameter (variable) --> Pathname
我们可以暂时关闭“路径名扩展”:
$ set -f
$ echo *.{ext1,ext2}
*.ext1 *.ext2
“路径名扩展”接收两个参数:*.ext1
和*.ext2
。
$ set +f
$ echo *.{ext1,ext2}
a.ext1 b.ext1 a.ext2 b.ext2
问题是我们不能将变量用于括号扩展。在“括号扩展”中使用变量
之前,已经进行了多次解释。
要扩展作为“变量扩展”的结果的“括号扩展”,您需要使用来将命令行重新提交给shell eval
。
$ list={ext1,ext2}
$ eval echo '*.'"$list"
大括号-> 变量 ->球形|| -> 括号 ->变量-> Glob
........在这里引用-> ^^^^^^ || 评估^^^^^^^^^^^^^^^^^^^^^^^^^^^
文件名的值不会对eval执行任何问题:
$ touch 'a;date;.ext1'
eval echo '*.'"$list"
a;date;.ext1 a.ext1 b.ext1 a.ext2 b.ext2
但是的值$list
可能不安全。但是,的值$list
由脚本编写者设置。脚本编写者可以控制eval
:仅不使用的外部设置值$list
。尝试这个:
#!/bin/bash
touch {a,b,c}.ext{1,2}
list=ext{1,2}
eval ls -l -- '*.'"$list"
更好的选择。
另一种选择(不使用eval)是使用Bash“扩展模式”:
#!/bin/bash
shopt -s extglob
list='@(ext1|ext2)'
ls -- *.$list
注意:请注意,两种解决方案(评估和模式)(按书面规定)对于带有空格或换行符的文件名都是安全的。但是对于$list
带空格的,将失败,因为$list
未加引号或eval删除了引号。
eval ls $secondList
在这里工作正常...您要完成什么?