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.