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>