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