Jak korzystać ze zmiennej Bash (ciąg) zawierającej cudzysłowy w poleceniu?

45

Niepowodzenie, uproszczony przykład:

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

Muszę dołączyć cytaty, jakby polecenie wyglądało tak:

rsync --archive --exclude="foo bar.txt" dir1 dir2
Reilly Beacom
źródło

Odpowiedzi:

52

Krótka odpowiedź: patrz BashFAQ # 50 („Próbuję umieścić polecenie w zmiennej, ale złożone przypadki zawsze zawodzą!”).

Długa odpowiedź: Umieszczanie poleceń (lub ich części) w zmiennych, a następnie przywracanie ich w stanie nienaruszonym jest skomplikowane. Gdy powłoka rozwija zmienną w wierszu poleceń, jeśli zmienna była w cudzysłowie, nie jest analizowana; jeśli nie było w cudzysłowach, spacje są analizowane jako łamanie argumentów, ale cudzysłowy i znak ucieczki nie są analizowane. W obu przypadkach umieszczanie cudzysłowów w wartości zmiennej nic nie robi.

Zwykle najlepszym sposobem na zrobienie tego rodzaju rzeczy jest użycie tablicy zamiast prostej zmiennej tekstowej:

FLAGS=(--archive --exclude="foo bar.txt")
rsync "${FLAGS[@]}" dir1 dir2
Gordon Davisson
źródło
Święty Jezu, to działa!
Sławomir
-2

Nie widzę problemu:

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

Może trzeba jeszcze raz podać wartość:

$ rsync "$FLAGS" dir1 dir2
Franck Lefort
źródło
5
echonie pokazuje tego, co myślisz. Spróbuj printargs() { printf "'%s' " "$@"; echo; }; printargs $FLAGS; printargs "$FLAGS"dowiedzieć się, dlaczego żadna z tych opcji nie działa.
Gordon Davisson