$ md="-l /tmp/test/my dir"
$ ls "$md"
ls: invalid option -- ' '
Try 'ls --help' for more information.
$ md="-l \"/tmp/test/my dir\""
$ ls "$md"
ls: invalid option -- ' '
Try 'ls --help' for more information.
Eu queria saber por que ambos não funcionam? Obrigado. Observe que o valor da variável contém
- uma opção
-l
- um argumento pathname que contém um espaço
- um espaço que separa os dois acima.
Meu problema real é: eu escrevi um scriptmyscript.sh
#! /bin/bash
old_dest=""
while getopts ":l:t" opt; do
case $opt in
l)
old_dest="--link-dest \"$OPTARG\""
;;
esac
done
rsync -a --delete "$old_dest" /path/to/source /path/to/dest
Eu quero chamar o script como um comando com -l
opção.
myscript.sh -l "/media/t/my external hdd/backup/old one"
Como devo escrever a parte do script que atribui a old_dest
?
Como você está usando o bash e como o bash oferece suporte a arrays, sugiro tornar old_dest um array:
Instrumentei a chamada para rsync para ser uma chamada para printf para mostrar o comando e cada argumento em uma linha separada. Quando executado:
O resultado é:
A razão pela qual seu comando não funciona é porque a remoção de citações/divisão de palavras não é aplicada recursivamente.
Portanto,
"$old_dest"
é expandido para o argumento SINGLE a seguir:Tudo isso é UM argumento, porque a variável estava entre aspas duplas. (E essas aspas duplas são removidas, mas as aspas duplas que resultaram da expansão , ou seja, faziam parte do valor da variável, não são removidas.)
Se você usasse
$old_dest
em vez disso, obteria vários argumentos, mas não da maneira que deseja. Você obteria os CINCO argumentos a seguir:Isso ocorre porque você obteria expansão variável seguida de divisão de palavras, conforme abordado no manual. Você não obteria a expansão variável seguida pela interpretação das aspas na variável. E as aspas não seriam retiradas, então o argumento final seriam os quatro caracteres:
one"
.A maneira certa de fazer isso, conforme abordado em outra resposta, é usar matrizes Bash.
Em uma nota separada, você pode apreciar como o Tcl lida com citações e divisão de palavras. Provavelmente é mais intuitivo, embora eu tenha tanta prática com a divisão de palavras do shell que tenho que pensar mais em Tcl do que em shell.