A resposta de Stephen Rauch descreve o problema. Eu tenho uma solução diferente.
Mas primeiro: por que você está colocando um comando tão longo em uma variável? Só assim você pode imprimi-lo? Por que não apenas usar a opção detalhada (show commands) do shell?
set -v (your_command) set +v
A opção x
(rastreamento de execução) é semelhante;
tente o acima com set -x
e set +x
para ver a diferença.
Se você gosta dos dois, pode combiná-los com set -vx
e set +vx
.
É uma péssima ideia criar uma string a partir de uma sequência de palavras,
separados por espaços,
e tente separá-lo para recuperar as palavras componentes originais.
Você encontrou uma das armadilhas.
Outra é a possibilidade teórica
que um nome de arquivo pode conter espaço (s);
seria impossível dizer na string de comando cat foo bar baz
que foo bar
é um nome de arquivo e baz
é outro
(e você viu isso criando a string como cat "foo bar" baz
não funciona bem também).
Estas questões e outras são discutidas aqui:
- Por que meu script de shell se sufoca no espaço em branco ou outros caracteres especiais?
- Implicações de segurança de esquecer de citar uma variável em shells bash / POSIX
Além disso, você não precisa de printf
apenas para concatenar strings.
Se você realmente quer construir sua linha de comando no armazenamento, e você está usando o bash, você pode usar uma variável array, assim:
DulicityCMD=(duplicity --log-file "$LOG_FILE" --progress --no-encryption --include="/etc" --include="/var/log" --include="/var/db" --include="/var/www" --include="/home" --exclude="**" / scp://[email protected]:22//home/duplicity/backups/"$VPSNAME")
Observe que eu coloquei $LOG_FILE
e $VPSNAME
entre aspas.
Você deve sempre citar todas as referências às variáveis do shell
a menos que você tenha uma boa razão para não
e você tem certeza de que sabe o que está fazendo.
Mas Stephen está certo: você não precisa citar as strings constantes
como "/etc"
, "/var/log"
, "/var/db"
e assim por diante.
(Mas, claro, você faz precisa citar "**"
,
porque *
é um caractere especial.)
Por questões de legibilidade, você pode dividir o acima em várias linhas.
Observe que a primeira linha diz =
e as linhas subsequentes dizem +=
,
porque eles estão adicionando ao que veio antes:
DulicityCMD=(duplicity --log-file "$LOG_FILE" --progress --no-encryption)
DulicityCMD+=(--include="/etc" --include="/var/log" --include="/var/db")
DulicityCMD+=(--include="/var/www" --include="/home" --exclude="**")
DulicityCMD+=(/ scp://[email protected]:22//home/duplicity/backups/"$VPSNAME")
Então você pode fazer
printf "%s\n" "${DulicityCMD[*]}" (to print the command) "${DulicityCMD[@]}" (to execute the command)
ou use sudo "${DulicityCMD[@]}"
, se precisar.
Veja bash (1) para mais informações sobre a sintaxe do bash,
e minha resposta aqui para ver mais sobre essa técnica de matriz.