我发现了一种奇怪的行为,我不知道如何解决。
$ 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
的行为?感谢。
额外说明:
我尝试使用双引号和单引号,但效果相同。
答案 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
。