symbolische Verknüpfung zu einem Verzeichnis und einem relativen Pfad

15

Ich habe einen Symlink mit absolutem Pfad zum Verzeichnis (Blink) angelegt und habe zum Beispiel 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 wechsle in das Verzeichnis Blink:

$ cd /tmp/A
$ pwd
/tmp/A
$ cd Blink
$ pwd
/tmp/A/Blink

cd ..Gibt mich zurück zu, /tmp/A aber wenn ich zum Beispiel ls ../footippe, bekomme ich eine Fehlermeldung:

ls: ../foo: No such file or directory

eingebauter cd befehl löst pfad nach bedarf auf, aber externe ls betrachten den .. als up-level von / tmp / B und können daher foo nicht finden.

Was ist das Problem hier? Kann ich die foo-Datei von / tmp / A / Blink über einen relativen Pfad wie ../foo abrufen?

user478681
quelle
Dieselbe
Peter.O am

Antworten:

13

Ich glaube nicht, dass du das schaffst. Heutzutage behalten Shells den Überblick darüber, wo sie sich gerade befinden. Sie verfolgen das aktuelle Arbeitsverzeichnis nach Namen und verlassen sich nicht nur auf das Dateisystem und das Betriebssystem, um es zu behalten. Das bedeutet, dass das eingebaute cdElement die symbolische Verknüpfung "sichern" kann, anstatt nur ".." Ketten direkt zu folgen.

Aber wenn Sie ausführen ls ../foo, lsist nicht bekannt, dass die Shell durch Verfolgen von symbolischen Links zu einem Verzeichnis gelangt ist. lswerde ein stat()auf "../foo" machen. Der Teil ".." stammt aus dem aktuellen Verzeichnis, das nur einen einzigen Eintrag ".." für das übergeordnete Verzeichnis enthält. Die ganze symbolische Verknüpfungssache ändert nichts an der Art und Weise, wie Verzeichnisse ein einzelnes "." und ein einzelner ".." Eintrag. Durch symbolische Links fügt der Kernel eine zusätzliche Indirektionsebene in die Dateipfade ein. Wenn Sie "../whatever" an open()oder übergeben stat(), verwendet der Kernel nur das aktuelle Arbeitsverzeichnis des Prozesses, der den Aufruf ausführt, um herauszufinden, welches einzelne Verzeichnis mit ".." benannt ist.

Bruce Ediger
quelle
17

Die Shell speichert das aktuelle Arbeitsverzeichnis in $PWD. Das ist, was für die Shell-Builtins cdund verwendet wird pwd, und es behandelt Symlinks wie normale Verzeichnisse, wie Sie gesehen haben. Manchmal ist das hilfreich, manchmal nicht.

Sie finden das reale Verzeichnis mit pwd(geben Sie help pwdfür weitere Details ein):

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

Ebenso cdhat eine Option -P(wieder help cdist dein Freund):

$ cd /tmp/A/Blink
$ pwd
/tmp/A/Blink
$ cd -P ..
$ pwd -P
/tmp

Schließlich können Sie die "Funktion" insgesamt deaktivieren:

$ set -P
$ cd /tmp/A/Blink
$ pwd
/tmp/B
ams
quelle
Danke, mir ist die Funktion set -P bekannt, aber ich war verwirrt über das Verhalten des Befehls ls ...
user478681
Wie ich bereits sagte, macht das set -PVerhalten von use und ls langsam Sinn. :)
ams
2

Bruce und ams gaben wunderschöne Antworten und erklärten das Verhalten dahinter. Aber um das zu tun ls ../foo, wonach Sie gefragt haben, könnten Sie sich für so etwas entscheiden

ls $(dirname $PWD)/foo
Antti Vikman
quelle
1

Du kannst es nicht machen, weil /tmp/A/Blink es tatsächlich so ist /tmp/B. Funktioniert also ls ../A/foo.

Sie können stattdessen finden es sinnvoll, in der Lage sein cd in die reale /tmp/B Verzeichnis, anstatt die aliased /tmp/A/Blink. Um dies zu tun, können Sie stattdessen die folgende Funktion verwenden cd(die Sie in Ihre .bashrc einfügen können)

lcd() { cd $(readlink -f "$1"); }

lcdFunktioniert natürlich auch für normale und symbolisch verknüpfte Verzeichnisse.
Hinweis: readlink -fWirkt auf das endgültige Ziel der Verknüpfung (wenn Verknüpfungen hintereinander geschaltet sind).

Peter.O
quelle
1
cd -Pscheint einfacher.
JW013
@ jw013: Du hast recht; es ist. Ich war mir dessen nicht bewusst .. danke ..
Peter.O