Tuesday, January 19, 2010

Difference between $*, $@, "$*" and "$@"

They are all related to "all the arguments to the shell", but behave differently. The following script demonstrates each one of $*, $@, "$@" and "$*" in turn by echoing out the arguments passed in:
#! /bin/bash

echo +--- Using "\$*"

cnt=1
for i in $*
do
  echo arg$cnt: $i
  cnt=$(($cnt+1))
done

echo +--- Using \"\$*\"

cnt=1
for i in "$*"
do
  echo arg$cnt: $i
  cnt=$(($cnt+1))
done

echo +--- Using "\$@"

cnt=1
for i in $@
do
  echo arg$cnt: $i
  cnt=$(($cnt+1))
done

echo +--- Using \"\$@\"

cnt=1
for i in "$@"
do
  echo arg$cnt: $i
  cnt=$(($cnt+1))
done
Running the script, produces the following output:
sharfah@starship:~> echoArgs.sh  mars "kit kat" twix
+--- Using $*
arg1: mars
arg2: kit
arg3: kat
arg4: twix
+--- Using "$*"
arg1: mars kit kat twix
+--- Using $@
arg1: mars
arg2: kit
arg3: kat
arg4: twix
+--- Using "$@"
arg1: mars
arg2: kit kat
arg3: twix
When unquoted, $* and $@ do the same thing. They treat each "word" (sequence of non-whitespace characters) as a separate argument. This leads to the single argument "kit kat" being broken into two which may not be desired. When quoted, $* and $@ behave differently. "$*" treats the entire argument list as a single argument, but "$@" treats the arguments just as they were when passed in.

So, which should you use? In almost all cases you would use "$@" in order to preserve arguments with spaces (or quoted arguments) when being passed in on the command line or from one script to another. Never use the unquoted $* or $@ unless you are absolutely sure that you won't need to deal with arguments with spaces in them. If you need to combine all arguments into one, use "$*".

No comments:

Post a Comment