6

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

$ 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

这一次, at 声明只会~被扩展,这导致我不能将它作为参数传递给ls. 但是,从字面上传递相同的字符串会产生预期的结果。

问题是:

  • 为什么有时扩展有时不扩展?
  • 如何模仿$var1with的行为$var2

谢谢。

额外说明:

我用双引号和单引号尝试了同样的方法,但结果同样糟糕。

4

1 回答 1

11

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.

于 2013-07-07T15:00:32.730 回答