1988

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 ("$@") 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 "$@", assume I changed the $* part of the script accordingly.)

Unquoted $*

$*with no quotes will interpret every space-delimited argument as separate, even if the arguments are quoted:

# $*
$ ./demo.sh "keep it together" two
keep
it
together
two

We want it to print out keep it together and two as separate lines, so this is wrong.

Quoted "$*"

Now let’s try it with "$*":

# "$*"
$ ./demo.sh "keep it together" two
keep it together two

As you can see, it interpreted the two arguments as one long argument, so it’s still not quite there.

Unquoted $@

Now let’s try with $@:

# $@
$ ./demo.sh "keep it together" two
keep
it
together
two

Unquoted $@ acts exactly like unquoted $*.

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.