Bash: the difference between $* and $@ and what that means for working with filenames containing spaces

29 November, 2005 - 19:39
Categories:

Lets's start with a citation about the special parameters $* and $@ from the bash manual:

*
Expands to the positional parameters, starting from one. When the expansion occurs within double quotes, it expands to a single word with the value of each parameter separated by the first character of the IFS special variable. That is, "$*" is equivalent to "$1c$2c...", where c is the first character of the value of the IFS variable. If IFS is unset, the parameters are separated by spaces. If IFS is null, the parameters are joined without intervening separators.
@
Expands to the positional parameters, starting from one. When the expansion occurs within double quotes, each parameter expands to a separate word. That is, "$@" is equivalent to "$1" "$2" .... When there are no positional parameters, "$@" and $@ expand to nothing (i.e., they are removed).

Apparently both $* and $@ expand to the positional parameters. The difference about the expanding between double quotes can be important if you have to deal with filenames with spaces. The following example should clarify the difference. Consider the two files filename.txt and filename with spaces.txt:

$> cat filename.txt
hello
$> cat "filename with spaces.txt"
hi there
$> 

We now write the following simple bash script, which we will give the fancy name test.sh:

#!/bin/bash
 
echo '--- cat $* ---'
cat $*
 
echo '--- cat $@ ---'
cat $@
 
echo '--- cat "$*" ---'
cat "$*"
 
echo '--- cat "$@" ---'
cat "$@"

and execute it with the two files above as arguments:

$> ./test.sh filename.txt "filename with spaces.txt"
--- cat $* ---
hello
cat: filename: No such file or directory
cat: with: No such file or directory
cat: spaces.txt: No such file or directory
--- cat $@ ---
hello
cat: filename: No such file or directory
cat: with: No such file or directory
cat: spaces.txt: No such file or directory
--- cat "$*" ---
cat: filename.txt filename with spaces.txt: No such file or directory
--- cat "$@" ---
hello
hi there

In most cases you probably will need the last construct: "$@".