Wie verwende ich eine Bash-Variable (Zeichenfolge), die Anführungszeichen in einem Befehl enthält?

45

Fehlerhaftes, vereinfachtes Beispiel:

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

Ich muss die Anführungszeichen einfügen, als ob der Befehl so wäre:

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

Antworten:

54

Kurze Antwort: Siehe BashFAQ # 50 ("Ich versuche, einen Befehl in eine Variable zu schreiben , aber die komplexen Fälle schlagen immer fehl!").

Lange Antwort: Das Einfügen von Befehlen (oder Teilen von Befehlen) in Variablen und die anschließende Wiederherstellung ist kompliziert. Wenn die Shell eine Variable in der Befehlszeile erweitert und die Variable in Anführungszeichen gesetzt wurde, wird sie nicht analysiert. Wenn es nicht in Anführungszeichen steht, werden Leerzeichen als Argumentumbrüche analysiert, aber Anführungszeichen und Escapezeichen werden nicht analysiert. In beiden Fällen ist es nicht sinnvoll, Anführungszeichen in den Wert der Variablen einzufügen.

Normalerweise ist die beste Möglichkeit, dies zu tun, die Verwendung eines Arrays anstelle einer einfachen Textvariablen:

FLAGS=(--archive --exclude="foo bar.txt")
rsync "${FLAGS[@]}" dir1 dir2
Gordon Davisson
quelle
Heiliger Jesus, es funktioniert!
Slawomir
-2

Ich sehe das Problem nicht:

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

Möglicherweise müssen Sie den Wert noch einmal zitieren:

$ rsync "$FLAGS" dir1 dir2
Franck Lefort
quelle
5
echozeigt nicht, was Sie denken, dass es ist. Versuchen Sie herauszufinden printargs() { printf "'%s' " "$@"; echo; }; printargs $FLAGS; printargs "$FLAGS", warum keine dieser Optionen funktioniert.
Gordon Davisson