当使用变量时,带有大括号扩展的 mkdir 似乎会失败

当使用变量时,带有大括号扩展的 mkdir 似乎会失败

Ubuntu 14.04.5 LTS GNU bash,版本 4.3.11(1)-release (x86_64-pc-linux-gnu)

mkdir -vp test{1..3}/{a,b,c}

工作正常

mkdir: created directory 'test1'
mkdir: created directory 'test1/a'
mkdir: created directory 'test1/b'
mkdir: created directory 'test1/c'
mkdir: created directory 'test2'
mkdir: created directory 'test2/a'
mkdir: created directory 'test2/b'
mkdir: created directory 'test2/c'
mkdir: created directory 'test3'
mkdir: created directory 'test3/a'
mkdir: created directory 'test3/b'
mkdir: created directory 'test3/c'


S=1;E=3; LANG=EN mkdir -pv test{$S..$E}/{a,b,c}

mkdir: created directory 'test{1..3}'
mkdir: created directory 'test{1..3}/a'
mkdir: created directory 'test{1..3}/b'
mkdir: created directory 'test{1..3}/c'

似乎不起作用。

不成功的是单引号和双引号。

S=1;E=3; LANG=EN mkdir -pv 'test{$S..$E}/{a,b,c}'
mkdir: created directory 'test{$S..$E}'
mkdir: created directory 'test{$S..$E}/{a,b,c}'


 S=1;E=3; LANG=EN mkdir -pv 'test{'$S'..'$E'}/{a,b,c}'
 mkdir: created directory 'test{1..3}'
 mkdir: created directory 'test{1..3}/{a,b,c}'

 S=1;E=3; LANG=EN mkdir -pv "test{S1..S3}/{a,b,c}"
 mkdir: created directory 'test{S1..S3}'
 mkdir: created directory 'test{S1..S3}/{a,b,c}'

我知道我可以使用 for 循环,对参数数量有限制,文件夹可能存在问题,或者使用 printf 或类似的设置,如“类似问题”部分所示。

然而我更想知道为什么这个特定的通配符案例对我来说失败了。

我在这个问题的评论中找到了一个可能的解决方案

Bash 脚本单引号参数与通配值

qouting 用户 Galaxy You can use eval to expand the whole line before executing it, e.g. $out=(eval "grep ..."), however, this works only if your input is trusted. – 这使得

S=1;E=3; LANG=EN eval mkdir -pv "test{$S..$E}/{a,b,c}"

mkdir: created directory 'test1'
mkdir: created directory 'test1/a'
mkdir: created directory 'test1/b'
mkdir: created directory 'test1/c'
mkdir: created directory 'test2'
mkdir: created directory 'test2/a'
mkdir: created directory 'test2/b'
mkdir: created directory 'test2/c'
mkdir: created directory 'test3'
mkdir: created directory 'test3/a'
mkdir: created directory 'test3/b'
mkdir: created directory 'test3/c'

工作。

答案1

是的,在 Bash 中,大括号扩展是在扩展变量之前的第一件事。这意味着这不能按您想要的方式工作:

$ a=1; b=5; echo {$a..$b}
{1..5}

(首先展开大括号,给出{$a..$b},然后展开变量,给出{1..5}。)

但你可以这样做(如果你想出它的用途):

$ aa=123;ab=456; echo $a{a,b}
123 456

使用evalworks,因为它强制进行额外的评估,但这通常不是一个好主意,因为它会评估例如命令扩展和包含$符号的文件名中的其他内容,这通常不是您想要的。

如果您有一个数字范围,如下所示,您可以使用循环:

S=1;E=3;
for (( i=$S; i <= $E; i++ )) ; do 
     echo $i
done

或者:

while [ $S -le $E ] ; do 
    echo $S 
    S=$[ $S + 1] 
done 

另外,zsh是否按照您的需要进行大括号扩展:

$ zsh -c 'a=1; b=5; echo {$a..$b}'
1 2 3 4 5

相关内容