Comment utiliser une variable Bash (chaîne) contenant des guillemets dans une commande?

39

Echec, exemple simplifié:

FLAGS='--archive --exclude="foo bar.txt"'
rsync $FLAGS dir1 dir2

Je dois inclure les guillemets comme si la commande était comme ceci:

rsync --archive --exclude="foo bar.txt" dir1 dir2
Reilly Beacom
la source

Réponses:

46

Réponse courte: voir BashFAQ # 50 ("J'essaie de mettre une commande dans une variable, mais les cas complexes échouent toujours!").

Réponse longue: Il est compliqué de placer des commandes (ou des parties de commandes) dans des variables, puis de les restituer intactes. Lorsque le shell développe une variable sur la ligne de commande, si la variable est entre guillemets doubles, elle n'est pas analysée. s'il n'était pas entre guillemets, les espaces qu'il contient sont analysés comme des sauts d'arguments, mais les guillemets et les caractères d'échappement ne sont pas analysés. Dans les deux cas, mettre des guillemets dans la valeur de la variable ne sert à rien.

Habituellement, la meilleure façon de faire ce genre de chose est d'utiliser un tableau au lieu d'une simple variable de texte:

FLAGS=(--archive --exclude="foo bar.txt")
rsync "${FLAGS[@]}" dir1 dir2
Gordon Davisson
la source
-1

Je ne vois pas le problème:

$ FLAGS='--archive --exclude="foo bar.txt"'
$ echo $FLAGS
--archive --exclude="foo bar.txt"

Peut-être devrez-vous citer à nouveau la valeur:

$ rsync "$FLAGS" dir1 dir2
Franck Lefort
la source
3
echo ne montre pas ce que vous pensez qu'il est. Essayer printargs() { printf "'%s' " "$@"; echo; }; printargs $FLAGS; printargs "$FLAGS" pour voir pourquoi aucune de ces options ne fonctionne.
Gordon Davisson