Symlink-Aliasing-Dateien in Unterverzeichnissen, ohne das aktuelle Verzeichnis zu ändern

11

Es scheint einfach zu sein, eine Datei mit einer neuen Datei in einem Unterverzeichnis zu verknüpfen, ohne Unterverzeichnisse zu verschieben. Aber etwas an der Syntax ist verwirrend und widerspricht dem, was ich erwarten würde. Hier ist ein Testfall:

mkdir temp
cd temp
mkdir deploy
echo "Contents of the build file!" > deploy/resources.build.php
ln -s deploy/resources.build.php deploy/resources.php
cat deploy/resources.php #bad symlink

Dies erzeugt nur einen defekten Symlink! Ich führe dies in einem Setup-Skript für die Build-Umgebung aus, daher möchte ich nach Möglichkeit vermeiden, das aktuelle Arbeitsverzeichnis zu ändern.

ln -s deploy/resources.build.php resources.php
cat deploy/resources.php

Funktioniert auch nicht, da der Symlink im temporären Verzeichnis anstelle des Deploy-Unterverzeichnisses erstellt wird.

cd deploy
ln -s resources.build.php resources.php
cd ..

Das funktioniert, aber ich würde lieber wissen, wie es geht, ohne die Verzeichnisse zu wechseln.

Verwenden eines vollständigen Pfads wie:

/home/whatever/src/project/temp/stuff/temp/deploy/resources.build.php

Funktioniert, ist aber unkompliziert und etwas unpraktisch, insbesondere in einer Build-Umgebung, in der alle Projektmaterialien zwischen Builds und dergleichen unterschiedlich sein können.

Wie kann ich einen Symlink zwischen zwei Dateien in einem Unterverzeichnis erstellen, ohne in dieses und aus diesem Unterverzeichnis zu wechseln und der neuen Datei "Alias" einen neuen Namen zu geben?

Kzqai
quelle

Antworten:

10

Aber etwas an der Syntax ist verwirrend und widerspricht dem, was ich erwarten würde.

Die Argumente für lnin der Form, in der Sie es verwenden, sind:

ln [OPTION] ... [-T] TARGET LINK_NAME (1. Form)

Die verwirrende, nicht intuitiv ist , dass , wenn Sie einen symbolischen Link erstellen, das Ziel für Argument lnist kein Pfad zu einer Datei zu erwarten sein, sondern der Inhalt des Symlink angelegt werden. Wenn Sie einen Moment darüber nachdenken, ist es offensichtlich, dass es so sein muss. Erwägen:

$ echo foo >foo
$ ln -s foo bar1
$ ln -s $PWD/foo bar2
$ cat bar1
foo
$ cat bar2
foo
$ ls -l bar1 bar2
lrwxrwxrwx 1 matt matt  3 Dec 29 16:29 bar1 -> foo
lrwxrwxrwx 1 matt matt 29 Dec 29 16:29 bar2 -> /home/matt/testdir/foo

In diesem Beispiel erstelle ich zwei Symlinks mit den Namen "bar1" und "bar2", die auf dieselbe Datei verweisen. lszeigt jedoch, dass die Symlinks selbst unterschiedliche Inhalte haben - einer enthält einen absoluten Pfad und einer einen relativen Pfad. Aus diesem Grund würde einer weiterarbeiten, selbst wenn er in ein anderes Verzeichnis verschoben würde, und der andere würde nicht:

$ mv bar2 /tmp
$ cat /tmp/bar2
foo
$ mv bar1 /tmp
$ cat /tmp/bar1
cat: /tmp/bar1: No such file or directory

So bedachte, dass wir in der Lage sein müssen , sowohl relative als auch absolute Symlinks zu machen, und sogar gebrochen Symlinks zu schaffen , die un-gebrochen werden wird , wenn die Zieldatei später erstellt wird, das Ziel hat Argument als Freitext interpretiert werden, anstatt die Pfad zu einer bereits vorhandenen Datei.

Wenn Sie eine Datei mit dem Namen deploy / resources.php erstellen möchten, die mit deploy / resources.build.php verknüpft ist, müssen Sie entscheiden, ob Sie einen absoluten Symlink erstellen möchten (der gegen den zu verschiebenden Symlink ausfallsicher ist, aber unterbrochen wird, wenn der Ziel wird verschoben) oder ein relativer Symlink (der so lange funktioniert, wie sowohl der Symlink als auch das Ziel zusammen verschoben werden und dieselben relativen Pfade beibehalten).

Um einen absoluten Symlink zu erstellen, haben Sie folgende Möglichkeiten:

$ ln -s $PWD/deploy/resources.build.php deploy/resources.php

Um einen relativen Pfad zu erstellen, müssen Sie zunächst den relativen Pfad von der Quelle zum Ziel ermitteln. In diesem Fall können Sie Folgendes tun, da sich Quelle und Ziel relativ zueinander im selben Verzeichnis befinden:

$ ln -s resources.build.php deploy/resources.php

Wenn sie sich nicht im selben Verzeichnis befinden, müssen Sie stattdessen Folgendes tun:

$ ln -s ../foo/f bar/b

In diesem Fall, auch wenn foound barsind sowohl im aktuellen Verzeichnis, müssen Sie ein gehören ../in das ln Ziel , weil es beschreibt , wie finden faus dem Verzeichnis enthalten b.

Das ist eine extrem lange Erklärung, aber hoffentlich hilft es Ihnen, die lnSyntax ein wenig besser zu verstehen .

godlygeek
quelle
3

Sie können den Link in einer Subshell wie folgt erstellen:

  (cd deploy && ln -s resources.build.php resources.php && cat resources.php)

Wenn die Ausführung der Subshell beendet ist, befinden Sie sich immer noch im richtigen Verzeichnis.

Alternativ können Sie es versuchen

 ln -s resources.build.php deploy/resources.php

Dies funktioniert auch , wenn nicht berücksichtigt wird , dass sich die Datei resources.build.php nicht in dem Verzeichnis befindet, in dem Sie den Befehl ausgeben, sondern sich tatsächlich in ./deploy befindet .

MariusMatutiae
quelle
Das ist schwarze Magie, Sir!
Kzqai
1

Dies verwirrte mich, bis mir klar wurde, dass ein Symlink im Grunde eine Konfigurationsdatei ist. dh wie würde ich diese Pfaddaten in eine einfache Textdatei schreiben:

ln -s [target] [link name]

wird:

echo [target] > [link name]

Der Fehler , dass ich (und wahrscheinlich OP) machte im Denken ln Bedürfnisse über die Datei wissen , dass es zielt. Es ist mir egal. Es werden nur einige Pfadinformationen in eine Datei geschrieben. Dies ist ein durchaus sinnvoll ln Befehl ein :

ln -s /path/doesnt/exist/file.err
ll
file.err -> /path/doesnt/exist/file.err

Daher:

ln -s deploy/resources.build.php deploy/resources.php

Erzeugt eine Simlink-Datei, die resources.phpin dem ./deployOrdner aufgerufen wird, der auf die Datei resources.build.phpim Ordner verweist ./deploy/deploy/.

Das ist unwahrscheinlich, was Sie wollen und gibt einen schlechten (defekten) Link. An dem Link ist nichts auszusetzen. Wenn Sie diese Datei dort ablegen, funktioniert der Link. (Wie von anderen betont) wollten ich und das OP jedoch:

ln -s resources.build.php deploy/resources.php
Martin
quelle