Este é um código ruim. getopt
é praticamente inutilizável¹. Use o getopts
shell embutido (ele tem duas vantagens: ele pode funcionar e está disponível em todas as plataformas POSIX).
O que o args=$(getopt optstring $*); set -- $args
faz é:
- Divida cada argumento da linha de comando no espaço em branco e substitua-o pela lista de palavras delimitadas por espaço em branco.
- Pegue cada uma das palavras resultantes e interprete-as como um padrão curinga. Se o padrão corresponder a pelo menos um arquivo, substitua o padrão pela lista de arquivos correspondentes.
- Transmita a lista de palavras resultante para o comando
getopt
.
- Armazena a saída do comando
getopt
na variável args
. Esta é uma string que consiste nos argumentos da linha de comando unidos com espaço em branco como o separador, e reordenados para ter opções e seus argumentos, então --
, então operandos não opcionais.
- Divida essa string no espaço em branco, interprete cada palavra como um padrão curinga e substitua o padrão pela lista de arquivos correspondentes, se houver algum.
- Use a lista resultante como argumentos posicionais.
Em shells ao estilo Bourne / POSIX, $foo
é o operador “split + glob”. Você precisa de aspas duplas para obter o valor de uma variável: "$foo"
. Mas em zsh, $foo
funciona de maneira diferente: ela se expande para o valor de foo
, exceto quando foo
está vazio. Então, em zsh, você obtém um único parâmetro posicional.
O primeiro uso do operador split + glob poderia ser evitado escrevendo getopt optstring "$@"
: isso passaria os parâmetros posicionais exatamente para getopt
. Mas ao analisar a saída de getopt
, a divisão é inevitável (você pode desabilitar a globulação), porque getopt
usa espaços para separar argumentos. O problema com getopt
é que a saída é ambígua: não há como distinguir um espaço que estava em um argumento de um espaço que getopt
adicionou como separador.
O jeito certo de fazer isso é com getopts
. É robusto e portátil.
while getopts optstring OPTLET; do
# We got the option -$OPTLET
case $OPTLET in
…
esac
done
shift $((OPTIND-1))
# Now the positional parameters are just the non-option operands
¹ Pelo menos a versão do BSD. A versão GNU adiciona recursos que a tornam utilizável.