Warum schlägt mkdir in einem Skript mit BIN_DIR = "~ / bin /" fehl (keine solche Datei oder kein solches Verzeichnis)?

Antworten:

10

Die Fehlermeldung wird ausgegeben, weil die Tilde ~zitiert wird, wie in Zannas Antwort beschrieben . Wenn Sie das verwenden möchten ~, sollte der relevante Teil des Skripts sein:

BIN_DIR=~/bin/

Wenn Sie die Zeichenfolge aus irgendeinem Grund in Anführungszeichen setzen möchten, können Sie die Umgebungsvariable verwenden $HOME:

BIN_DIR="$HOME/bin/"

Meiner Meinung nach ist der zweite Ansatz eine bessere Praxis.

pa4080
quelle
6
Es ist nichts Falsches daran, ~Skripte zu verwenden. Es funktioniert genauso wie in der Befehlszeile. Das Problem ist, dass das Zitieren die Tilde-Expansion blockiert, wie in Zannas Antwort erläutert .
Terdon
@terdon, ich stimme zu. Aber ich habe nicht gesagt, dass etwas nicht stimmt, aber es ist eine bessere Idee, weil Sie weniger aufpassen sollten.
pa4080
5
Aber hier gibt es absolut keinen Unterschied zwischen der Befehlszeile und einem Skript. Die Tatsache, dass dies in einem Skript enthalten ist, ist völlig irrelevant. Sie würden genau den gleichen Fehler in der Befehlszeile haben. Das Problem ist das Zitieren, nicht dass es in einem Skript steht.
Terdon
Das ist zwar völlig richtig, aber es ist auch richtig, dass die Verwendung $HOMEin Skripten eine gute Idee ist.
Nachtisch
3
@ pa4080 Können Sie eine Erklärung hinzufügen, warum es Ihrer Meinung nach besser ist, zu erweitern, $HOMEals eine Tilde-Erweiterung zu verwenden? Die einzige Erklärung, die Sie gegeben haben, ist zu sagen: "Es ist eine bessere Idee, weil Sie weniger Aufmerksamkeit schenken sollten." Ich habe keine Ahnung was das heißt. Können Sie es in einer Bearbeitung erläutern? Ohne sie gibt es nichts, was Ihre Antwort stützt, also gehört sie sicherlich dazu. Tilde - Erweiterung wurde von POSIX , die für eine ganze Weile und die Hash - Bang Zeile des Skripts ist #!/bin/bashalso nehme ich an Portabilität ist nicht der Grund.
Eliah Kagan
23

Es funktioniert nicht, weil ~zitiert wird. Doppelte Anführungszeichen " unterdrücken die Tilde-Erweiterung . Es gibt kein Verzeichnis mit dem Literalnamen ~/bin. Wie in man bash(Hervorhebung von mir) erklärt:

Tilde-Erweiterung

Wenn ein Wort mit einem nicht zitierten Tilde-Zeichen (`~ ') beginnt , werden alle Zeichen vor dem ersten nicht zitierten Schrägstrich (oder alle Zeichen, wenn kein nicht zitierter Schrägstrich vorhanden ist) als Tilde-Präfix betrachtet. Wenn keines der Zeichen im Tilde-Präfix in Anführungszeichen gesetzt wird, werden die Zeichen im Tilde-Präfix nach der Tilde als möglicher Anmeldename behandelt. Wenn dieser Anmeldename die Nullzeichenfolge ist, wird die Tilde durch den Wert des Shell-Parameters HOME ersetzt. Wenn HOME nicht festgelegt ist, wird stattdessen das Home-Verzeichnis des Benutzers ersetzt, der die Shell ausführt. Andernfalls wird das Tilde-Präfix durch das Home-Verzeichnis ersetzt, das dem angegebenen Anmeldenamen zugeordnet ist.

Sie können die Anführungszeichen entfernen , da dies ~das einzige Zeichen im Pfad ist ~/bin, das bewirkt, dass die Shell eine Erweiterung ausführt. In diesem Fall möchten wir die Erweiterung. Die Shell führt keine weiteren Erweiterungen für das Ergebnis der Tilde-Erweiterung durch, zumindest nicht in Bash 4 , das alle aktuellen oder remote aktuellen Ubuntu-Versionen haben . Selbst wenn Ihr Home-Verzeichnis ungewöhnliche Zeichen wie Leerzeichen enthält, ist dies in Ordnung.

Oder Sie können $HOMEanstelle von verwenden ~, da die Parametererweiterung nicht durch doppelte Anführungszeichen, sondern nur durch einfache Anführungszeichen unterdrückt wird . Die doppelten Anführungszeichen stellen sicher, dass der erweiterte Wert selbst keinen weiteren Erweiterungen unterliegt, sodass keine Wortaufteilung oder Dateinamenerweiterung erfolgt. Funktioniert also $HOMEauch mit seltsam benannten Home-Verzeichnissen, solange Sie die doppelten Anführungszeichen behalten.

Zanna
quelle
Nach dieser Aussage "wird die Parametererweiterung nicht durch doppelte Anführungszeichen, sondern nur durch einfache Anführungszeichen unterdrückt" : Die Ausgabe von cd '~'ist -bash: cd: ~: No such file or directory.
pa4080
2
@ pa4080 Die Erweiterung von ~ist nicht Teil der Parametererweiterung.
Barmar