POSIXly, a análise das opções deve parar em -- ou no primeiro argumento que não seja de opção (ou não-opção-argumento), o que ocorrer primeiro. Então, em
cp -R file1 -t /mybackup file2 -f
que está em file1 , por isso cp deve recursivamente copiar todos os file1 , -t , /mybackup e file2 para o diretório -f .
GNU getopt(3) no entanto (aquele GNU cp usa as opções de análise (e aqui você está usando o GNU cp desde que você está usando a opção -t específica do GNU)), a menos que o $POSIXLY_CORRECT variável de ambiente é definida, aceita opções após os argumentos. Então, é realmente equivalente à análise de estilo de opção POSIX:
cp -R -t /mybackup -f -- file1 file2
O shell getopts embutido, mesmo no shell GNU ( bash ), somente manipula o estilo POSIX. Também não suporta opções longas ou opções com argumentos opcionais.
Se você quiser analisar as opções da mesma maneira que o GNU cp , você precisará usar a API GNU getopt(3) . Para isso, se no Linux, você pode usar o utilitário getopt aprimorado de util-linux ( essa versão aprimorada do getopt O comando também foi portado para alguns outros Unices, como o FreeBSD ).
Esse getopt reorganizará as opções de maneira canônica, permitindo que você analise simplesmente com um loop while/case .
$ getopt -n "$0" -o t:Rf -- -Rf file1 -t/mybackup file2
-R -f -t '/mybackup' -- 'file1' 'file2'
Você costuma usá-lo como:
parsed_options=$(
getopt -n "$0" -o t:Rf -- "$@"
) || exit
eval "set -- $parsed_options"
while [ "$#" -gt 0 ]; do
case $1 in
(-[Rf]) shift;;
(-t) shift 2;;
(--) shift; break;;
(*) exit 1 # should never be reached.
esac
done
echo "Now, the arguments are $*"
Observe também que getopt analisará as opções da mesma maneira que o GNU cp . Em particular, ele suporta as opções longas (e as digita abreviadamente) e respeita as variáveis de ambiente $POSIXLY_CORRECT (que, quando definidas, desabilitam o suporte para opções após argumentos) da mesma maneira que o GNU cp faz.
Observe que o uso do gdb e a impressão dos argumentos que o getopt_long() recebe podem ajudar a criar os parâmetros para getopt(1) :
(gdb) bt
#0 getopt_long (argc=2, argv=0x7fffffffdae8, options=0x4171a6 "abdfHilLnprst:uvxPRS:T", long_options=0x417c20, opt_index=0x0) at getopt1.c:64
(gdb) set print pretty on
(gdb) p *long_options@40
$10 = {{
name = 0x4171fb "archive",
has_arg = 0,
flag = 0x0,
val = 97
}, {
name = 0x417203 "attributes-only",
[...]
Então você pode usar getopt como:
getopt -n cp -o abdfHilLnprst:uvxPRS:T -l archive... -- "$@"
Lembre-se de que a lista de opções suportadas do GNU cp pode mudar de uma versão para a próxima e que getopt não poderá verificar se você passa um valor legal para a opção --sparse , por exemplo. / p>