I found a weird behavior that I don't know how to workaround.
$ var1=*
$ echo $var1
Audiobooks Downloads Desktop (etc.)
$ ls $var1
Audiobooks:
Downloads:
(etc)
All seems OK. At declaration, the variable gets expanded and everything else works. But see this:
$ 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
This time, at declaration only ~
gets expanded, which produces that I cannot pass it as an argument to ls
. However, passing the same string literally produces the expected results.
Questions are:
$var1
with $var2
?Thanks.
Extra notes:
I tried the same with double and single quotes, but with the same bad results.
The order in which the shell parses various aspects of the command line is not obvious, and it matters for things like this.
First, the wildcards aren't expanded at declaration, they're expanded after the variable value is substituted (note: in these examples I'll pretend I have your filesystem):
$ 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)
BTW, the ~
is expanded at declaration, confusing things even further:
$ var2=~
$ echo "$var2" # again, double-quotes let me see what's actually in the variable
/home/yajo
The problem with ~/rpmbuild/{SRPMS,RPMS/*}/enki-*.rpm1
is that while the shell does wildcard expansion (*
) on the value after substitution, it doesn't do brace expansion ({SRPMS,RPMS/*}
), so it's actually looking for directory names with braces and commas in the name... and not finding any.
The best way to handle this is generally to store the file list as an array; if you do this right, everything gets expanded at declaration:
$ 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...
Note that arrays are a bash extension, and will not work in plain POSIX shells. So be sure to start your script with #!/bin/bash
, not #!/bin/sh
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With