I have the following simplified bash script
#!/bin/bash
files=("$@")
if [ "X$files" = "X" ]; then
files=$HOME/print/*.pdf;
fi
for file in "${files[@]}"; do
ls "$file";
done
If I pass arguments (file names) as parameters this script will print the proper file names. On the other hand, if I don't pass arguments, it will print
/home/user/print/*.pdf: No such file or directory
Why are the file names not expanded in this case, and how do I fix it? Note that I use the files=("$@")
and "${files[@]}"
constructs because I read that it is to be preferred over the usual "files=$*".
Best Answer
You're assigning
files
as a scalar variable instead of an array variable.In
You're assigning some string like
/home/highsciguy/print/*.pdf
to the$files
scalar (aka string) variable.Use:
or
instead. The shell will expand that globbing pattern into a list of file paths, and assign each of them to elements of the
$files
array.The expansion of the glob is done at the time of the assignment.
You don't have to use non-standard sh features, and you could use your system's
sh
instead ofbash
here by writing it:set
is to assign the"$@"
array of positional parameters.Another approach could have been to store the globbing pattern in a scalar variable:
And have the shell expand the glob at the time the
$files
variable is expanded.Here, because
$files
is not quoted (which you shouldn't usually do), its expansion is subject to word splitting (which we've disabled here) and globbing/filename generation.So the
*.pdf
will be expanded to the list of matching files. However, if$HOME
contained wildcard characters, they could be expanded too, which is why it's still preferable to use an array variable.