You need to first take the time to understand exactly how the shell uses arguments, and the "
@" form of parameter expansion in particular.
To start with, read these three links:
http://mywiki.wooledge.org/Arguments
http://mywiki.wooledge.org/WordSplitting
http://mywiki.wooledge.org/Quotes
Now,
$@ outputs all the parameter arguments as separate entities, but
only if you quote it first. Otherwise the shell simply word-splits it back out again. So
always double quote it. The "
${array[@]}" array expansions work the same way.
Your first attempt:
Code:
commands=$@
for arg in $commands ; do
This is bad. First it puts the entire contents of
$@ into a single scalar variable, then it relies on word-splitting that variable back into pieces for the
for loop to iterate over.
Now if you really want to back-up/duplicate the
$@ parameters, set them into an
array.
Code:
commands=( "$@" )
for arg in "${commands[@]}"; do
Now the strings are never left unprotected.
Do note however that while the
$@ parameters start with "
1", array indexes start with "
0", so you'll have to do a bit of math if you need them to match up. Or else start with a dummy 0 array entry before you populate it.
Code:
commands[0]="" #start with an empty array 0
commands+=( "$@" ) #+= appends entries to an existing array
unset commands[0] #unset 0, so command 1 will be the first one in the array
for arg in "${commands[@]}"; do
This way "
$1" and "
${commands[1]}", etc. should be identical.
How can I use array variables?
http://mywiki.wooledge.org/BashFAQ/005
Now for a few more points:
When using
bash or
ksh, it's recommended to use
((..)) for numerical tests, and
[[..]] for string/file tests and complex expressions. Avoid using the old
[..] test unless you specifically need POSIX-style portability.
http://mywiki.wooledge.org/ArithmeticExpression
http://mywiki.wooledge.org/BashFAQ/031
http://wiki.bash-hackers.org/commands/classictest
http://wiki.bash-hackers.org/syntax/...nal_expression
When testing the contents of a single variable for multiple values, you should use a single
case statement, instead of multiple
if..elif..thens.
http://wiki.bash-hackers.org/syntax/ccmd/case
Finally, since you appear to be trying to create an option parser of some kind, I recommend you take a look at the built-in
getopts instead. No need to reinvent the wheel if you don't have to.
http://wiki.bash-hackers.org/howto/getopts_tutorial