Positional Parameters in Bash

Been long since I posted something on Bash and as usual, I again post something from Mrugesh’s (floyd_n_milan) key board. This time its an explanation of Positional parameters in Bash, which was actually a reply to a question in GLUG-BOM mailing list. I felt the explanation to be more clear than what I found in many books on the same, hence here goes his explanation (slightly edited).

$* expands the positional parameters. 

Positional parameters are arguments passed to a command.
When you run your script by doing, say, 

$ ./image-resize image1 image2 image3 

the positional parameters get set to ./image-resize,
image1, image2 and image3. 

The positional parameters can be used as the variables
$0 to $n where n is any integer. $0 is always set to
the name of the script, in this case image-resize.
The parameters from $1 onwards are the actual
arguments. So in this case, 

$1 == image1
$2 == image2 and
$3 == image3 

These are read only variables. You can't manually
assign a value to them. You must use either set or shift. 

When you process the arguments, you can either call them
individually, or, as is most common, process them in a
loop, one by one. You've used the second method. 

$* and $@ are two variables that can be used to query
all the positional parameters together. When unquoted,
they are subject to IFS word splitting like any other
variable in bash. What this means is that if your arguments
have spaces or newlines embedded in them, they'll be
split up to be two different entities. 

The safe way is to double quote ( " ) the variables,
which prevents this internal splitting. 

Mind the double quotes. VERY important. 

Here's an example: 

$ set "foo bar" baz blah
$ # "foo bar" is intended to be a single argument.
$ # set can be used to set various bash options and
   positional parameters.
$ echo $1
foo bar
$ echo $2
$ echo $3
$ for i in $@; do echo '==> '${i}' <=='; done
==> foo <==
==> bar <==
==> baz <==
==> blah <==
$ # Notice that foo and bar have been split up. Undesirable.
$ for i in $*; do echo '==> '${i}' <=='; done
==> foo <==
==> bar <==
==> baz <==
==> blah <==
$ # When unquoted $@ and $* produce the same result.
$ for i in "$@"; do echo '==> '${i}' <=='; done
==> foo bar <==
==> baz <==
==> blah <==
$ # I suppose this is what you wanted?
$ for i in "$*"; do echo '==> '${i}' <=='; done
==> foo bar baz blah <==
$ # When double quoted, $@ and $* differ vastly..
$ # And that's not the result you wanted either.
$ # Always use "$@".

And here is a small addition from cydork,

<cydork> add that when you use “$*” the positional parameters will be separated with first char of IFS 😉

And one additional point from Mrugesh himself,

the ${array[@]} and ${array[*]} behave in a similar manner


3 thoughts on “Positional Parameters in Bash

Leave a Reply

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

WordPress.com Logo

You are commenting using your WordPress.com 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