Warum kann ich nicht zu einer zitierten Tilde wechseln ('~')?

32

Ich bin mir sicher, dass dies eine grundlegende Frage ist, aber kann mir jemand erklären, warum ich Folgendes kann:

cd ~
cd bin
cd ~/bin
cd 'bin'

Aber nicht

cd '~'
cd '~/bin'

Ich muss zu cdeinem Verzeichnispfad mit einem Leerzeichen in einem der Verzeichnisnamen, also benötige ich die Anführungszeichen (es ist Windows Program Filesunter Wein). Ich kann es mit zwei cdBefehlen umgehen, aber warum kann ich keine ~Anführungszeichen setzen?

Wenn ich schreibe cd '~'(oder cd "~") erhalte ich:

bash: cd: ~: No such file or directory
B.Tanner
quelle
29
Stellen Sie sich folgende Frage: Wenn dies nicht funktioniert hätte, wie würden Sie cdin ein Verzeichnis mit dem Namen ~wechseln?
Jörg W Mittag
2
Als Randbemerkung, wenn Sie ein Skript schreiben, sollten Sie lieber absolute Pfade verwenden und cdalles zusammen vermeiden . Verwenden Sie Variablen, um Pfadnamen zu speichern, die Sie nicht mehrmals eingeben möchten, z. B.pf=~/.wine/drive_c/Program\ Files/; cp /path/to/file "$pf"
dessert
8
@jamesqf: Warum sollte ein vernünftiges System besser als ich wissen, wie ich meine Dateien und Verzeichnisse benennen möchte? Außerdem habe ich nie verstanden, warum Unix die magische In-Band-Signalisierung von Pfadkomponententrennzeichen und Pfadabschlusszeichen einsetzte. Was stimmt nicht mit einer Datei / einem Verzeichnis namens /oder NUL?
Jörg W Mittag
3
@ JörgWMittag vermutlichcd ./~
k_g
2
@jamesqf Zu beachten ist, dass Unix-Dateisysteme in der Vergangenheit jedes Zeichen in einem Dateinamen außer '/' (Pfadtrennzeichen) und '\ 0' (NUL - Zeichen für Zeichenfolgenbeendigung) zuließen - wie Jorg bemerkt. Keine weiteren Einschränkungen. Es gab viele Unix-Dateisystemimplementierungen, daher hätte die Einführung von Einschränkungen in einem von ihnen die Kompatibilität beeinträchtigt und die Komplexität erhöht - und wurde als "seltsam" angesehen! Und '~' - Erweiterung wurde erst vor relativ kurzer Zeit in csh und in bash eingeführt. Dateien / Verzeichnisse mit '~' Zeichen sind nicht unbekannt (zB myfile ~ als Backup für myfile).
SusanW

Antworten:

78

Wie @karel in seiner Antwort angemerkt hat, ~handelt es sich um ein Sonderzeichen, das von Bash in das Home-Verzeichnis des aktuellen Benutzers erweitert wird. Siehe Bashs Handbuch zu "Tilde Expansion" oder suchen Sie in der Manpage ( man bash) nach der Überschrift "Tilde Expansion" .

Jede Art von Anführungszeichen ~verhindert diese Tilde-Erweiterung.


Um Ihre Frage zu beantworten, wie Sie es weiterhin cdin ein Verzeichnis mit Leerzeichen im Namen verwenden können, gibt es einige Alternativen:

  • Lassen Sie Anführungszeichen weg und schließen Sie die Leerzeichen stattdessen mit Backslashes:

    cd ~/foo/spaces\ are\ cool/bar
  • Zitiere den Rest des Pfades, aber lasse sie um die Tilde und den ersten Schrägstrich herum weg:

    cd ~/"foo/spaces are cool/bar"

    Wie Sie sehen, können Sie Zeichenfolgen in Anführungszeichen und nicht in Anführungszeichen gesetzte Zeichenfolgen in Bash verketten, indem Sie sie einfach ohne Leerzeichen nebeneinander schreiben.

  • Verwenden Sie die Umgebungsvariable $HOMEanstelle der Tilde, die in "doppelten Anführungszeichen" (aber nicht in "einfachen Anführungszeichen") erweitert wird:

    cd "$HOME/foo/spaces are cool/bar"
Byte Commander
quelle
3
@rexkogitans ~'/...'wird nicht funktionieren und ist nicht das, was diese Antwort hat. ~/'...'oder ~/"..."wird funktionieren.
HDV
tld; dr: weil das Shell-Syntax ist
Sergiy Kolodyazhnyy
@hvd danke. Tippfehler behoben. Dies ist die vollständigste Antwort und erklärt auch, wie das, was das OP tun möchte, gelöst werden kann. ~/'path'ist der Weg zu gehen.
rexkogitans
1
@hvd nur wenig Neugier, warum würde nicht ~'/...'funktionieren? Der Schrägstrich ist kein Sonderzeichen, daher sollte er entweder innerhalb oder außerhalb der Anführungszeichen funktionieren.
Kodos Johnson
6
@KodosJohnson Schauen Sie sich die Bash-Manpage über "Tilde Expansion" an. Der relevante Absatz davon wird auch in der Antwort des Nachtischs unten zitiert. TL; DR: Tilde-Erweiterung findet statt, wenn das erste Zeichen in einem Wort eine nicht zitierte Tilde ist, wird alles zwischen dieser Tilde und dem nächsten nicht zitierten Schrägstrich als "Tilde-Präfix" betrachtet. Wenn dieses Präfix kein gültiges Zeichen wie +, -, eine Zahl oder ein Benutzername ist (Anführungszeichen sind dort ebenfalls nicht zulässig), schlägt die Erweiterung fehl und Sie erhalten ein literales ~ -Zeichen.
Byte Commander
17

~ ist ein Sonderzeichen, das von der Shell als Basisverzeichnis des angemeldeten Benutzers interpretiert wird. '~' wird von der Shell als Literalzeichen interpretiert, nicht als Home-Verzeichnis des angemeldeten Benutzers, da das Einschließen einer Zeichenfolge in zwei einfache Anführungszeichen dazu führt, dass diese Zeichenfolge als Literaltextzeichenfolge interpretiert wird.

karel
quelle
~ist kein Alias ​​in dem Sinne bash, dass es interpretiert wird: Aliase ermöglichen das Ersetzen eines Wortes durch eine Zeichenfolge, wenn es als erstes Wort eines einfachen Befehls verwendet wird. . Wie ich in meiner Antwort unten erläutere, handelt es sich eher um eine Erweiterung.
Dessert
15

Dies ist eine bashFunktion namens Tilde-Erweiterung . Zitieren man bash:

Wenn ein Wort mit einem nicht in Anführungszeichen stehenden Tilde-Zeichen ("~") beginnt , werden alle Zeichen vor dem ersten nicht in Anführungszeichen stehenden Schrägstrich (oder alle Zeichen, wenn kein nicht in Anführungszeichen stehender Schrägstrich vorhanden ist) als Tilde-Präfix betrachtet. Wenn keines der Zeichen im Tilde-Präfix in Anführungszeichen gesetzt ist, 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 gesetzt ist, wird stattdessen das Home-Verzeichnis des Benutzers ersetzt, der die Shell ausführt.

Damit die Erweiterung funktioniert, muss das Tilde-Zeichen ~nicht in Anführungszeichen gesetzt sein. Andernfalls wird das Zeichen wörtlich genommen und cdschlägt fehl, wenn ~im aktuellen Verzeichnis kein Verzeichnis mit dem Namen vorhanden ist. Siehe diese ausführliche Antwort für eine Erklärung des Zitierens in bash. Wenn Sie einen Teil des Pfades angeben müssen, können Sie daher:

  1. Zitieren Sie mindestens die Zeichen, die in einfache Anführungszeichen gesetzt werden müssen, z

    ~/dir' 'with' 'spaces/

    oder

    ~/'dir with spaces/'
  2. Zitieren Sie mindestens die Zeichen, die in Anführungszeichen gesetzt werden müssen, z

    ~/dir" "with" "spaces/

    oder

    ~/"dir with spaces/"
  3. Zitieren Sie nur die Zeichen, die mit Backslashes zitiert werden müssen, z

    ~/dir\ with\ spaces/

Tilde Expansion hat einige weitere interessante Funktionen, zB:

  • ~+Erweitert auf den Wert von PWD, dh das aktuelle Arbeitsverzeichnis
  • ~-Erweitert auf den Wert von OLDPWD, dh das vorherige Arbeitsverzeichnis
  • ~john Erweitert das Ausgangsverzeichnis, das mit dem Anmeldenamen "john" verknüpft ist.
Dessert
quelle
Übrigens ist es auch in Ordnung, Backslashes zu übertreiben. zB $ touch a; cd \a. (Ich dachte, dies könnte in Schwierigkeiten geraten cd \n, aber das Experimentieren zumindest mit meiner Version bashdeutet darauf hin, dass es gut funktioniert.)
LSpice
1

Erkunden mit echoBefehl

Mit dem echoBefehl können Sie am einfachsten untersuchen, wie die Dinge in bash funktionieren . Im Falle der ~Verwendung dieses:

$ echo ~
/home/rick
$ echo '~'
~
$ echo "~"
~
$ echo `~`
bash: /home/rick: Is a directory

Wie Sie sehen, wird ein einfaches Anführungszeichen oder doppelte Anführungszeichen ~als Zeichenfolge interpretiert und nicht als Variable erweitert. Wenn Sie Backticks (`) verwenden, wird es als Befehl ausgeführt und generiert eine Fehlermeldung.

WinEunuuchs2Unix
quelle