Angenommen, ich möchte den folgenden Befehl in einer Variablen speichern
cd "/cygdrive/c/Program Files/"
Also mache ich das
dir="cd \"/cygdrive/c/Program Files/\""
Das sollte den Befehl zum Navigieren zum Programmdateiverzeichnis speichern. Wenn ich also $ dir eingebe, gehe ich in dieses Verzeichnis. Um zu überprüfen, ob die Zitate ordnungsgemäß maskiert wurden, tippe ich
echo $dir
das gibt mir
cd "/cygdrive/c/Program Files/"
Also sollte alles gut funktionieren. Wenn ich jedoch tippe,
$dir
Ich bekomme
bash: cd: "/cygdrive/c/Program: No such file or directory
Was mache ich falsch? Ich verwende Cygwin, aber ich gehe davon aus, dass dieses Problem generell für Bash gilt.
Antworten:
Kurze Antwort: siehe BashFAQ # 050 ("Ich versuche, einen Befehl in eine Variable einzufügen , aber die komplexen Fälle schlagen immer fehl!").
Lange Antwort: Wenn bash einen Befehl analysiert, werden Anführungszeichen analysiert, bevor Variablen ersetzt werden. Es geht nie zurück und analysiert Anführungszeichen in den Werten von Variablen neu, sodass sie nichts Nützliches tun. Die Verwendung von echo zur Überprüfung des Befehls ist völlig irreführend, da der Befehl nach dem Analysieren angezeigt wird. Wenn Sie sehen möchten, was wirklich ausgeführt wird, verwenden Sie entweder
set -x
die Shell-Druckbefehle, während sie ausgeführt werden, oder verwenden Sieprintf "%q " $dir; echo
anstelle des einfachen Echos.Wenn Sie einen komplexen Befehl speichern möchten (dh einen mit Leerzeichen oder anderen Sonderzeichen in den "Wörtern"), müssen Sie ihn anstelle einer einfachen Textvariablen in ein Array einfügen und ihn dann mit der Redewendung "$ {" erweitern Array [@]} ", wie folgt:
Wenn der Zweck darin besteht, eine einfach zu tippende Kurzschrift zu erstellen, ist dies eindeutig nicht der richtige Weg. Verwenden Sie stattdessen einen Shell-Alias oder eine Shell-Funktion:
oder
quelle
Wenn bash erweitert wird
$dir
, wird nur eine Wortaufteilung und ein Globbing durchgeführt. Word - Spaltung erzeugt drei Worte:cd
,"/cygdrive/c/Program
undFiles/"
. Dann ist der auszuführende Befehlcd
mit zwei Argumenten;cd
betrachtet nur das erste Argument"/cygdrive/c/Program
, das kein vorhandenes Verzeichnis ist.Wenn Sie eine vollständige Shell-Bewertung des Inhalts einer Variablen durchführen möchten, verwenden Sie
eval
:Beachten Sie, dass Sie doppelte Anführungszeichen benötigen
$dir
, da sonst zuerst eine Wortaufteilung durchgeführt und danneval
die Argumente mit Leerzeichen verknüpft werden. Dies würde hier zwar funktionieren, aber im Allgemeinen schlecht werden (z. B. wenn ein Dateiname zwei aufeinanderfolgende Leerzeichen enthält).Eine Zeichenfolge ist jedoch nicht der richtige Weg, um einen Shell-Befehl zu speichern, den Sie ausführen möchten. Sofern Sie keine ungewöhnlichen Anforderungen haben, sollten Sie stattdessen eine Funktion verwenden:
Wenn Sie wirklich daran interessiert sind, zu tippen
$dir
, um zu einem bestimmten Verzeichnis zu wechseln, und dies nicht nur ein einfaches Beispiel ist, geben Sie in bash 4shopt -s autocd
Ihr.bashrc
und set einDanach können Sie einfach
"/cygdrive/c/Program Files/"
oder"$dir"
an der Shell-Eingabeaufforderung eingeben, um in dieses Verzeichnis zu wechseln. Sie brauchen immer noch die doppelten Anführungszeichen$dir
; Wenn dir das nicht gefällt, benutze zsh anstelle von bash.quelle
Das Speichern von Befehlen in Variablen ist im Allgemeinen keine gute Idee. Dafür sind Funktionen und Aliase da.
Eher, als
Probieren Sie eines davon aus:
oder
oder
Das erste Formular, in dem der Name des Verzeichnisses in einer Variablen gespeichert wird, bedeutet etwas mehr Eingabe, aber es ist klarer, wenn Sie den Befehl ausführen, den Sie ausführen
cd
. Die zweite ist der nächsten, die Sie erreichen möchten. (Ich benutze Aliase nicht viel in Bash; ich bin mir nicht sicher, welchen Vorteil sie gegenüber Funktionen haben.)EDIT:
Und
dir
ist wahrscheinlich ein schlechter Name für einen Alias oder eine Funktion, da es einen vorhandenen Befehl mit diesem Namen gibt (es ist im Grunde eine Version vonls
, zumindest wenn Sie GNU-Coreutils haben).quelle
Storing commands in variables is generally not a good idea. That's what functions and aliases are for.
Versuchen
Aber noch genauer:
/programming/4334467/cygwin-using-a-path-variable-containing-a-windows-path-with-a-space-in-it
quelle