Command-Line Arguments in Shell Scripts
There are a few ways to loop over command-line arguments in shell scripts.
There’s $*
and $@
, and then there are quoted ("$*
and "$@"
) versions of
each. Each one behaves differently, but there’s one that you almost always want
to use.
Here’s a shell script named demo.sh
that will illustrate the difference:
#!/bin/sh
for argument in $*; do
echo "$argument"
done
(For each bit about $*
vs $@
vs "$*"
vs "$@"
, assume I changed the $*
part of the script accordingly.)
Unquoted $*
Unquoted $*
will ignore quotes in arguments:
# $*
$ ./demo.sh "keep it together" two
keep
it
together
two
This behaves exactly like ./demo.sh keep it together two
. We want it to print
out keep it together
and two
as separate lines, so this is wrong.
Unquoted $@
Now let’s try with $@
:
# $@
$ ./demo.sh "keep it together" two
keep
it
together
two
Unquoted $@
acts exactly like unquoted $*
.
Quoted "$*"
Now let’s try it with "$*"
:
# "$*"
$ ./demo.sh "keep it together" two
keep it together two
As you can see, it combined the two arguments into one long argument
Technically, it’s joining the two arguments with the $IFS
(or “internal field
separator”) variable. By default, "$IFS"
is three characters: a space, a tab,
and a newline. "$*"
only joins with the first character of $IFS
, so it print
the arguments with a space between them, but we can temporarily change it:
#!/bin/sh
IFS="GABE"
for argument in "$*"; do
echo "$argument"
done
$ ./demo.sh "keep it together" two
keep it togetherGtwo
In any case, it’s still not quite there, so let’s keep looking.
Quoted "$@"
And finally, the one that we always want to use, "$@"
:
# "$@"
$ ./demo.sh "keep it together" two
keep it together
two
At last, we have printed two lines for two arguments, appropriately split up according to how we passed them in as arguments.