How to use arguments like $1 $2 ... in a for loop?
In any Bourne-like shell, it's:
for arg
do printf 'Something with "%s"\n' "$arg"
done
That is, for
does loop on the positional parameters ($1
, $2
...) by default (if you don't give a in ...
part).
Note that that's more portable than:
for arg; do
printf 'Something with "%s"\n' "$arg"
done
Which was not POSIX until the 2016 edition of the standard nor Bourne (though works in most other Bourne-like shells including bash
even in POSIX mode)
Or than:
for arg in "$@"; do
printf 'Something with "%s"\n' "$arg"
done
Which is POSIX but doesn't work properly in the Bourne shell or ksh88 when $IFS
doesn't contain the space character, or with some versions of the Bourne shell when there's no argument, or with some shells (including some versions of bash
) when there's no argument and the -u
option is enabled.
Or than
for arg do
printf 'Something with "%s"\n' "$arg"
done
which is POSIX and Bourne but doesn't work in very old ash-based shells. I personally ignore that and use that syntax myself as I find it's the most legible and don't expect any of the code I write will ever end up interpreted by such an arcane shell.
More info at:
- http://www.in-ulm.de/~mascheck/various/bourne_args/
- What is the purpose of the “do” keyword in Bash for loops?
Now if you do want $i
to loop over [1..$#]
and access the corresponding elements, you can do:
in any POSIX shell:
i=1
for arg do
printf '%s\n' "Arg $i: $arg"
i=$((i + 1))
done
or:
i=1
while [ "$i" -le "$#" ]; do
eval "arg=\${$i}"
printf '%s\n' "Arg $i: $arg"
i=$((i + 1))
done
Or with bash
for ((i = 1; i <= $#; i++ )); do
printf '%s\n' "Arg $i: ${!i}"
done
${!i}
being an indirect variable expansion, that is expand to the content of the parameter whose name is stored in the i
variable, similar to zsh
's P
parameter expansion flag:
for ((i = 1; i <= $#; i++ )); do
printf '%s\n' "Arg $i: ${(P)i}"
done
Though in zsh
, you can also access positional parameters via the $argv
array (like in csh
):
for ((i = 1; i <= $#; i++ )); do
printf '%s\n' "Arg $i: $argv[i]"
done
I would use shift
. This one [ -n "$1" ]
means while arg-1 is non-empty, keep looping.
#! /bin/bash
while [ -n "$1" ]; do
echo "$1"
wget "https://ssl.gstatic.com/dictionary/static/sounds/de/0/$1.mp3"
shift
done