Ist das Ziel von symlink relativ zum übergeordneten Verzeichnis des Ziels und wenn ja, warum?

14

Ich habe folgende Dateistruktur:

build/
client/
  –> index.js

Und wenn ich versuche, einen symbolischen Link mit dem Namen "client" innerhalb des Build-Verzeichnisses zu erstellen, der auf das Client-Verzeichnis im CWD verweist, sieht das so aus

// Fails
$ pwd
/home/user/
$ ln -s client build/client 
$ stat build/client/index.js
stat: build/client/index.js: stat: Too many levels of symbolic links

Ich erhalte den oben angezeigten ELOOP-Fehler. Wenn ich den Zielpfad so ändere, dass er relativ zum Zielpfad ist, ist alles in Ordnung:

// Works
$ pwd
/home/user/
$ ln -s ../client build/client 
$ stat build/client/index.js
stat: <outputs file stats>

Ist dies das beabsichtigte Verhalten und erklären Sie bitte, warum ...

Fockverkauf
quelle
Dies hat wahrscheinlich etwas mit dem Effekt zu tun, dass mit ../ anstelle des relativen Pfades der absolute Pfad deklariert wird. Eine gute Übung ist es, immer den absoluten Pfad zu verwenden
Kiwy
Ich stimme der Best Practice zu, da ich sowohl für das Ziel als auch für das Ziel immer absolute Pfade verwendet habe. In den Manpages heißt es jedoch, dass relative Pfade für beide ...
jibsales 17.12.13

Antworten:

13

Für denjenigen, der nicht funktioniert, erhalten wir, wenn wir das ls -lErgebnis betrachten, Folgendes:

[sparticvs@sparta test]$ ls -l build/
total 0
lrwxrwxrwx. 1 sparticvs sparticvs 6 Dec 17 16:08 client -> client

Nun zu verstehen, was hier los ist. Schauen wir uns den Befehl an, den Sie aufgerufen haben:

ln -s client build/client

Laut Manpage gibt es zwei mögliche Übereinstimmungen für dieses Format

SYNOPSIS
       ln [OPTION]... [-T] TARGET LINK_NAME   (1st form)
       ln [OPTION]... TARGET... DIRECTORY     (3rd form)

Es stimmt mit dem ersten Formular überein (seit dem ersten). Nun kann der "Zielname" oder clientin Ihrem Fall (gemäß dem vollständigen lnHandbuch) beliebige Zeichenfolgen sein. Sie müssen sich im Moment zu nichts entschließen, können sich aber zu etwas in der Zukunft entschließen. Was Sie mit Ihrem Aufruf erstellen, ist ein "baumelnder Symlink", und das System hindert Sie nicht daran, diese zu erstellen.

Nun ist Ihr zweiter Aufruf ein ln -s ../client build/clientsogenannter "relativer Symlink" (wie Sie in Ihrem eigenen Beitrag vermerkt haben). Es gibt einen zweiten Typ, und das ist ein "absoluter Symlink", der beim Ausführen aufgerufen würde ln -s /home/user/client build/client.

Dies ist kein Fehler. Nach dem Handbuch heißt es:

Wenn Sie einen relativen Symlink an einem anderen Ort als dem aktuellen Verzeichnis erstellen, unterscheidet sich die Auflösung des Symlinks von der Auflösung der gleichen Zeichenfolge aus dem aktuellen Verzeichnis. Aus diesem Grund ziehen es viele Benutzer vor, zuerst das Verzeichnis zu ändern, in dem der relative Symlink erstellt wird, damit die Tab-Vervollständigung oder eine andere Dateiauflösung dasselbe Ziel findet wie das, was im Symlink platziert wird.

-- von info coreutils 'ln invocation'

Das heißt, Sie MÜSSEN entweder den relativen oder den absoluten Pfad zum Ziel verwenden.

sparticvs
quelle
5

Dies ist in der Tat das beabsichtigte Verhalten. Von der ln(1)Manpage:

Symbolische Links können beliebigen Text enthalten. Bei einer späteren Auflösung wird ein relativer Link in Bezug auf das übergeordnete Verzeichnis interpretiert.

Stellen Sie sich vor, der Symlink würde stattdessen relativ zu seiner Quelle und nicht zu seinem Ziel interpretiert. Wenn Sie es später beheben möchten, müssen Sie wissen, wie Ihre CWD bei der Erstellung aussah. Dies ist unsinnig, geschweige denn unmöglich.

Darüber hinaus erhalten Sie auf diese Weise eine übersichtliche und kompakte Methode zum Erstellen einer Verzeichnisstruktur, die Sie an einer beliebigen Stelle in der Verzeichnisstruktur ablegen können, ohne die Symlinks zu unterbrechen.

Um Ihnen ein Beispiel zu geben, was ich meine, nehmen wir an, Sie arbeiten an einem Projekt und Sie haben eine ganze Verzeichnisstruktur dafür eingerichtet, wie folgt:

$ ls -1 /home/you/project
thingummies/
widgets/
wizardry/

Angenommen, Sie möchten einen Symlink nach widgets/innen erstellen wizardry/. Sie haben zwei Möglichkeiten:

$ ln -s /home/you/project/widgets /home/you/project/wizardry

oder

$ ln -s ../widgets /home/you/project/wizardry

Wenn Sie dann versuchen /home/you/project, sich an eine andere Stelle zu bewegen , wird ein mit dem ersten Formular erstellter Symlink aufgrund der Suche unterbrochen /home/you/project/widgets. In der zweiten Form bleibt der Symlink funktionsfähig, da er ../widgets relativ zu dem Ort gesucht wird, an dem er sich befindet, unabhängig davon, wo sich dieser Ort in der Verzeichnisstruktur befindet.

Joseph R.
quelle