symbolischer Link zu einem Verzeichnis und relativer Pfad

symbolischer Link zu einem Verzeichnis und relativer Pfad

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 ../fooerhalte 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 cdund verwendet pwdund 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 pwdFolgendes eingeben ( help pwdfür weitere Details geben Sie Folgendes ein):

$ pwd
/tmp/A/Blink
$ pwd -L
/tmp/A/Blink
$ pwd -P
/tmp/B

Ebenso cdhat eine Option -P(wiederum help cdist 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 cdden symbolischen Link „sichern“ kann, anstatt nur „..“-Ketten direkt zu folgen.

Wenn Sie jedoch ausführen ls ../foo, lsist nicht bekannt, dass die Shell durch das Folgen symbolischer Links zu einem Verzeichnis gelangt ist. lsfü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 ../fooSie 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/fooes funktioniert.

Vielleicht finden Sie es stattdessen nützlich,CDzumreal /tmp/BVerzeichnis, 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"); }

lcdfunktioniert natürlich sowohl für normal als auch symbolisch verknüpfte Verzeichnisse.
Hinweis: readlink -fwirkt auf das endgültige Ziel des Links (wenn Links verkettet sind).

verwandte Informationen