Using $* in shell scripts is Nearly Always Wrong

(Bourne and Bash) Shell script writers bandy ‘$*’ about like it’s a stick of celery, but the truth is $* is nearly always the wrong thing to use. (For the clueless, $* expands to all the “positional parameters”, that is, all the parameters to the current script or function; it’s useful in cases where you want to pass the argument values for those parameters on to another program).

So why is $* wrong? Because it is evaluated before word splitting. In other words, if any of the arguments to your script had a space or other whitespace, then those arguments will become two when $* is evaluated. The following shell script can be used to verify this:

# Call this script “mytouch”
touch $*

… Now try to “mytouch” a file with a space in its name (yeah, well done, you just created two files with one command).

Does quoting it work? will “$*” solve your problems? It will fix the above example, right up to the point where you try to “mytouch” two or more files at once and then you’ll see the fallacy (hint: “$*” always expands to a single “word”).

So what is the correct solution? It’s simple: use “$@” instead. Note, that’s $@, with quotes around it. Hence “$@”. This specifically expands to one string for each actual argument. It works. Hallelujah. (And while I’m blathering on shell scripts, note that any unquoted variable expansion is also Nearly Always Wrong for pretty much the same reasons).


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s