Getting All Positional Parameters in POSIX Shell

The POSIX shell language provides two special parameters to get all positional parameters that the script was invoked with:

  1. $@
  2. $*

Both behave similarly when not double-quoted: field splitting is performed on each parameter. This means that even if an argument is quoted, it'll still be split up by IFS—which is whitespace by default—into separate fields. For example,

#!/bin/sh
#
# foo.sh

printf 'printing out all params using $*:\n'
for i in $*; do
  printf '%s\n' "$i"
done

printf '\nprinting out all params using $@:\n'
for i in $@; do
  printf '%s\n' "$i"
done

Outputs:

$ ./foo.sh a "b c d" e
printing out all params using $*:
a
b
c
d
e

printing out all params using $@:
a
b
c
d
e
$

These special parameters behave differently when between double quotes:

To better illustrate this important difference:

#!/bin/sh
#
# bar.sh

printf 'printing out all params using "$*":\n'
for i in "$*"; do
  printf '%s\n' "$i"
done

printf '\nprinting out all params using "$@":\n'
for i in "$@"; do
  printf '%s\n' "$i"
done

Outputs:

$ ./bar.sh a "b c d" e
printing out all params using "$*":
a b c d e

printing out all params using "$@":
a
b c d
e
$

Takeaways

Always Use "$@"


The Open Group Base Specifications Issue 7 (2.5.2 Special Parameters)