
Ich habe einen symbolischen Link mit dem absoluten Pfad zum Verzeichnis (Blink) erstellt und habe beispielsweise folgenden Baum:
$ ls -l /tmp/A
total 0
lrwxrwxrwx 1 root root 6 Apr 3 12:27 Blink -> /tmp/B
-rw-r--r-- 1 root root 0 Apr 3 12:27 foo
$ ls -l /tmp/B
total 0
-rw-r--r-- 1 root root 0 Apr 3 12:27 bar
dann gehe ich zu /tmp/A und ändere das Verzeichnis zu Blink:
$ cd /tmp/A
$ pwd
/tmp/A
$ cd Blink
$ pwd
/tmp/A/Blink
cd ..
gibt mich zurück, /tmp/A
aber wenn ich beispielsweise eingebe, ls ../foo
erhalte ich die Fehlermeldung:
ls: ../foo: No such file or directory
Der integrierte CD-Befehl löst den Pfad nach Bedarf auf, aber externe LS-Befehle betrachten .. als höherrangig zu /tmp/B und können daher foo nicht finden.
Was ist hier das Problem? Kann ich die foo-Datei aus /tmp/A/Blink über einen relativen Pfad wie ../foo abrufen?
Antwort1
Die Shell speichert das aktuelle Arbeitsverzeichnis in $PWD
. Dies wird für die Shell-Builtins cd
und verwendet pwd
und behandelt symbolische Links wie normale Verzeichnisse, wie Sie gesehen haben. Manchmal ist dies hilfreich, manchmal nicht.
Sie können das eigentliche Verzeichnis finden, indem Sie pwd
Folgendes eingeben ( help pwd
für weitere Details geben Sie Folgendes ein):
$ pwd
/tmp/A/Blink
$ pwd -L
/tmp/A/Blink
$ pwd -P
/tmp/B
Ebenso cd
hat eine Option -P
(wiederum help cd
ist es Ihr Freund):
$ cd /tmp/A/Blink
$ pwd
/tmp/A/Blink
$ cd -P ..
$ pwd -P
/tmp
Schließlich können Sie die „Funktion“ auch ganz deaktivieren:
$ set -P
$ cd /tmp/A/Blink
$ pwd
/tmp/B
Antwort2
Ich glaube nicht, dass Sie das tun können. Heutzutage behalten Shells den Überblick darüber, wie sie dahin gekommen sind, wo sie sind, sie behalten das aktuelle Arbeitsverzeichnis anhand des Namens im Auge, anstatt sich nur darauf zu verlassen, dass Dateisystem und Betriebssystem es behalten. Das bedeutet, dass die integrierte Funktion cd
den symbolischen Link „sichern“ kann, anstatt nur „..“-Ketten direkt zu folgen.
Wenn Sie jedoch ausführen ls ../foo
, ls
ist nicht bekannt, dass die Shell durch das Folgen symbolischer Links zu einem Verzeichnis gelangt ist. ls
führt ein stat()
auf „../foo“ aus. Der „..“-Teil stammt aus dem aktuellen Verzeichnis, das nur einen einzigen „..“-Eintrag für sein übergeordnetes Verzeichnis hat. Die ganze Sache mit den symbolischen Links ändert nichts daran, dass Verzeichnisse einen einzigen „.“ und einen einzigen „..“-Eintrag haben. Symbolische Links ermöglichen dem Kernel, eine zusätzliche Ebene der Indirektion in Dateipfade einzufügen. Wenn Sie „../wasauchimmer“ an open()
oder übergeben stat()
, verwendet der Kernel einfach das aktuelle Arbeitsverzeichnis des aufrufenden Prozesses, um herauszufinden, welches einzelne Verzeichnis durch „..“ benannt ist.
Antwort3
Bruce und ams haben wunderbare Antworten gegeben, die das Verhalten dahinter erklären. Aber um das, was ls ../foo
Sie gefragt haben, tatsächlich zu tun, könnten Sie etwas wie Folgendes verwenden:
ls $(dirname $PWD)/foo
Antwort4
Das kannst du nicht tun, denn/tmp/A/Blink
Isttatsächlich /tmp/B
. Also, ls ../A/foo
es funktioniert.
Vielleicht finden Sie es stattdessen nützlich,CDzumreal /tmp/B
Verzeichnis, statt des Alias /tmp/A/Blink
. Dazu können Sie die folgende Funktion anstelle von verwenden cd
(die Sie in Ihre .bashrc einfügen können)
lcd() { cd $(readlink -f "$1"); }
lcd
funktioniert natürlich sowohl für normal als auch symbolisch verknüpfte Verzeichnisse.
Hinweis: readlink -f
wirkt auf das endgültige Ziel des Links (wenn Links verkettet sind).