Ich möchte einen Befehl in ein Shell-Skript einfügen, das einen Symlink zu einem Verzeichnis erstellt, aber dieses Skript könnte immer wieder ausgeführt werden, sodass der Befehl bei nachfolgenden Aufrufen nichts ändern sollte.
Hier ist die Verzeichnisstruktur:
% tree /tmp/test_symlink
/tmp/test_symlink
├── foo
└── repo
└── resources
└── snippets
├── php.snippets
├── sh.snippets
├── snippets.snippets
├── sql.snippets
└── vim.snippets
Ich möchte einen Symlink in foo/
sogenannten Snippets erstellen, der auf das Verzeichnis verweist /tmp/test_symlink/repo/resources/snippets
.
Also laufe ich:
% ln -sfv /tmp/test_symlink/repo/resources/snippets /tmp/test_symlink/foo/snippets
'/tmp/test_symlink/foo/snippets' -> '/tmp/test_symlink/repo/resources/snippets'
was das gewünschte Ergebnis ergibt.
% tree /tmp/test_symlink
/tmp/test_symlink
├── foo
│ └── snippets -> /tmp/test_symlink/repo/resources/snippets
└── repo
└── resources
└── snippets
├── php.snippets
├── sh.snippets
├── snippets.snippets
├── sql.snippets
└── vim.snippets
5 Verzeichnisse, 5 Dateien
Wenn der Befehl jedoch erneut ausgeführt wird,
% ln -sfv /tmp/test_symlink/repo/resources/snippets /tmp/test_symlink/foo/snippets
'/tmp/test_symlink/foo/snippets/snippets' -> '/tmp/test_symlink/repo/resources/snippets'
Es wird ein Symlink zu einem Verzeichnis erstellt, in dem der Symlink bereits vorhanden ist. Symlink wird in das reale Verzeichnis eingefügt
% tree /tmp/test_symlink
/tmp/test_symlink
├── foo
│ └── snippets -> /tmp/test_symlink/repo/resources/snippets
└── repo
└── resources
└── snippets
├── php.snippets
├── sh.snippets
├── snippets -> /tmp/test_symlink/repo/resources/snippets
├── snippets.snippets
├── sql.snippets
└── vim.snippets
Warum passiert das und wie kann ich den Befehl so ändern, dass nachfolgende Aufrufe diesen seltsamen Effekt nicht erzeugen?
quelle
-n, --no-dereference treat LINK_NAME as a normal file if it is a symbolic link to a directory
.-T, --no-target-directory treat LINK_NAME as a normal file always
halten Sie es für besser, einen Symlink immer als Datei zu behandeln? Ich hätte gedacht, es wäre besser, die Verwendung dieser "speziellen" Optionen zu begrenzen?-T
wie Sieln
idempotent machen . Es gibt andere Möglichkeiten, das gleiche Ergebnis zu erzielen, wenn Sie es vorziehen, z. B. den Link zu löschen und neu zu erstellen, oder wenn Sie bereits wissenfoo
,ln -sfv /tmp/test_symlink/repo/resources/snippets /tmp/test_symlink/foo/
dass dies eine bessere Antwort ist (ich werde es aktualisieren).if
Aussagen über die Gegenwart des Symlink zu erkennen und den Befehl überspringen , wenn der Symlink existierte, aber die Skripte am Ende überladen und immer schwer zu lesen, war ich für etwas Idempotent aber einfach gehen, wie mitmkdir -p
keine Tests , keine Logik, nur gute-T
, aber das Ende meiner Antwort stellt eine andere Lösung dar, die nicht verwendet wird-T
.Das Beste, was ich hier feststellen kann, ist, dass sich der
ln
Befehl beim zweiten Durchlauf wiecp
oder verhält.mv
Wenn er ein "Verzeichnis" unter <Ziel> sieht, wird die Datei darin abgelegt, andernfalls wird <Ziel> nicht abgelegt existiert, wird es <destination> machen. (Das ist es, was der "Slashdot" -Trick vermeidet - dh er stellt sicher, dass das <Ziel> existiert und ein Verzeichnis ist).Aber ich könnte mich irren.
In beiden Fällen scheint dies zu funktionieren
quelle