如何强制bash扩展变量以将其作为参数传递?

时间:2013-07-07 08:10:02

标签: bash variables expand

我发现了一种奇怪的行为,我不知道如何解决。

$ var1=*

$ echo $var1
Audiobooks Downloads Desktop (etc.)

$ ls $var1
Audiobooks:

Downloads:
(etc)

一切似乎都好。在声明时,变量被扩展,其他一切都可以工作。但请看这个:

$ var2=~/rpmbuild/{SRPMS,RPMS/*}/enki-*.rpm

$ echo $var2
/home/yajo/rpmbuild/{SRPMS,RPMS/*}/enki-*.rpm

$ ls $var2
ls: no se puede acceder a /home/yajo/rpmbuild/{SRPMS,RPMS/*}/enki-*.rpm: No existe el fichero o el directorio

$ ls /home/yajo/rpmbuild/{SRPMS,RPMS/*}/enki-*.rpm
/home/yajo/rpmbuild/RPMS/noarch/enki-12.10.3-1.fc18.noarch.rpm  /home/yajo/rpmbuild/SRPMS/enki-12.10.3-1.fc18.src.rpm
/home/yajo/rpmbuild/RPMS/noarch/enki-12.10.3-1.fc19.noarch.rpm  /home/yajo/rpmbuild/SRPMS/enki-12.10.3-1.fc19.src.rpm

这一次,在声明时,只有~被扩展,这导致我无法将其作为参数传递给ls。但是,传递相同的字符串会产生预期的结果。

问题是:

  • 为什么有时会扩张,有时不会?
  • 如何使用$var1模仿$var2的行为?

感谢。

额外说明:

我尝试使用双引号和单引号,但效果相同。

1 个答案:

答案 0 :(得分:10)

shell解析命令行的各个方面的顺序并不明显,对于这样的事情很重要

首先,通配符不会扩展通配符,它​​们会在替换变量值后展开(注意:在这些示例中我假装我有你的文件系统):

$ var1=*
$ echo "$var1"   # double-quotes prevent additional parsing of the variable's value
*
$ echo $var1     # without double-quotes, variable value undergoes wildcard expansion and word splitting
Audiobooks:

Downloads:
(etc)

顺便说一下,~ 在声明时被扩展,让事情更加混乱:

$ var2=~
$ echo "$var2"   # again, double-quotes let me see what's actually in the variable
/home/yajo

~/rpmbuild/{SRPMS,RPMS/*}/enki-*.rpm1的问题是,虽然shell对替换后的值进行了通配符扩展(*),但它不会进行大括号扩展({SRPMS,RPMS/*}),所以它实际上是在名称中查找带有大括号和逗号的目录名,但没有找到任何目录。

处理此问题的最佳方法通常是将文件列表存储为数组;如果你这样做,一切都会在宣言中得到扩展:

$ var2=(~/rpmbuild/{SRPMS,RPMS/*}/enki-*.rpm)
$ echo "${var2[@]}"   # This is the proper way to expand an array into a word list
/home/yajo/rpmbuild/RPMS/noarch/enki-12.10.3-1.fc18.noarch.rpm  etc...

请注意,数组是bash扩展,在普通POSIX shell中不起作用。因此,请务必使用#!/bin/bash启动您的脚本,而不是#!/bin/sh