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.