Eu tenho um problema ao passar parâmetros se os parâmetros puderem conter curingas e / ou espaços, se esses parâmetros forem opcionais. Como isso soa bem abstrato, vamos dar um pequeno exemplo: O seguinte script de shell some_command.sh
espera 2 ou 3 argumentos. O primeiro argumento é suposto ser uma opção de linha de comando, o segundo argumento é opcional e, se presente, deve ser uma opção de linha de comando do formulário --NAME=VALUE
, e o argumento final é obrigatório e pode ser qualquer coisa:
#!/bin/bash
# This is file some_command.sh
# Synopsis:
# some_command.sh --switch1=val1 [--switch2=val2] arg
echo "switch1: $1"
shift
if [[ "$1" == --*=* ]]
then
echo "switch2 ($1) detected"
shift
fi
echo argument is ${1:?argument missing}
Vamos supor que eu esteja chamando some_command.sh
de algum outro script, caller.sh
, da seguinte maneira:
#!/bin/bash
# This is file caller.sh
if [[ ${1:-x} == x ]]
then
switch="--abc=long argument"
else
switch=""
fi
some_command.sh "--exclude=*~" "$switch" arg
Observe as citações. As aspas em torno de --exclude
são necessárias, porque a expressão curinga não deve ser expandida pelo shell e as cotações em torno de "$switch"
são necessárias, porque $switch
pode conter texto com espaços e o argumento não deve ser dividido em os espaços.
A intenção é que, se executarmos caller.sh x
, isso deve resultar em
some_command.sh "--exclude=*~" "--abc=long argument" arg
e se executarmos, digamos, caller.sh y
, isso deve se transformar em
some_command.sh "--exclude=*~" arg
O caller.sh
que eu forneci aqui, não funciona corretamente, porque no último caso, ele seria executado
some_command.sh "--exclude*~" "" arg
que está incorreto.
Eu tentei prefixar o comando com eval
. Embora isso resolvesse o problema com $switch
, também removeria as cotas em torno de "--exclude"
e os curingas seriam avaliados pelo shell.
Acho que eu poderia continuar com o eval
e usar um nível extra de cotação, ou seja, "\"--exclude*~\""
, mas essa é uma solução terrível. Eu me pergunto se alguém tem uma maneira mais limpa de fazer isso.
Caso você esteja se perguntando por que eu cheguei a esta pergunta: Eu tropecei no problema ao escrever scripts invocando zip
, e já que esses scripts deveriam ser capazes de lidar com espaços em nomes de arquivos.
BTW, o problema, conforme indicado, ocorre com bash
e zsh
. Também estou interessado em soluções inteligentes, que funcionam apenas com uma dessas camadas.