Em qualquer shell parecido com o Bourne, é:
for arg
do printf 'Something with "%s"\n' "$arg"
done
Ou seja, for faz um loop nos parâmetros posicionais ( $1 , $2 ...) por padrão (se você não der uma in ... part).
Note que isso é mais portátil do que:
for arg; do
printf 'Something with "%s"\n' "$arg"
done
Que não era POSIX até a edição de 2016 do padrão nem Bourne (embora funcione na maioria dos outros shells semelhantes a Bourne incluindo bash mesmo no modo POSIX)
Ou então:
for arg in "$@"; do
printf 'Something with "%s"\n' "$arg"
done
Qual é o POSIX, mas não funciona corretamente no shell Bourne ou no ksh88 quando $IFS não contém o caractere de espaço, ou com algumas versões do shell Bourne quando não há argumento, ou com alguns shells (incluindo alguns versões de bash ) quando não há argumento e a opção -u está ativada.
Ou
for arg do
printf 'Something with "%s"\n' "$arg"
done
que é POSIX e Bourne, mas não funciona em shells muito antigas baseadas em cinzas. Eu pessoalmente ignoro isso e uso essa sintaxe como eu acho que é o mais legível e não espere que qualquer código que eu escrevo acabe sendo interpretado por um shell tão arcano.
Mais informações em:
Agora, se você quiser que $i faça um loop sobre [1..$#] e acesse os elementos correspondentes, faça o seguinte:
em qualquer shell POSIX:
i=1
for arg do
printf '%s\n' "Arg $i: $arg"
i=$((i + 1))
done
ou:
i=1
while [ "$i" -le "$#" ]; do
eval "arg=\${$i}"
printf '%s\n' "Arg $i: $arg"
i=$((i + 1))
done
Ou com bash
for ((i = 1; i <= $#; i++ )); do
printf '%s\n' "Arg $i: ${!i}"
done
${!i} sendo uma expansão de variável indireta, que é expandida para o conteúdo do parâmetro cujo nome é armazenado na variável i , semelhante ao sinalizador de expansão do parâmetro zsh P :
for ((i = 1; i <= $#; i++ )); do
printf '%s\n' "Arg $i: ${(P)i}"
done