Wie kann ich viele defekte Symlinks erneut verlinken?

54

Ich habe einen Verzeichnisbaum, auf eine Reihe von symbolischen Links zu Dateien unter hat /home... allerdings habe ich bewegt /homezu /mnt/homeund brauchen einen Weg , um alle der Symlinks „neu verknüpfen“. Existiert eine solche Funktionalität oder muss ich dazu ein Skript schreiben?

Als Beispiel habe ich so etwas wie das Folgende:

[root@trees ~]# ls -l /mnt/home/someone/something
total 4264
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 a -> /home/someone/someotherthing/a
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 b -> /home/someone/someotherthing/b
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 c -> /home/someone/someotherthing/c
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 d -> /home/someone/someotherthing/d
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 e -> /home/someone/someotherthing/e

/mnt/home/someone/something/subdir:
total 4264
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 a -> /home/someone/someotherthing/subdir/a
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 b -> /home/someone/someotherthing/subdir/b
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 c -> /home/someone/someotherthing/subdir/c
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 d -> /home/someone/someotherthing/subdir/d
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 e -> /home/someone/someotherthing/subdir/e

Ich möchte einen Befehl, der alle symbolischen Links zu finden und zu den gleichen Orten relink aber darunter /mnt/homestatt/home

Existiert ein solcher Befehl?

Josh
quelle

Antworten:

55

Es gibt keinen Befehl zum erneuten Ausrichten einer symbolischen Verknüpfung. Sie können sie lediglich entfernen und eine neue erstellen. Angenommen, Sie haben GNU-Dienstprogramme (z. B. unter nicht eingebettetem Linux oder Cygwin), können Sie mit dem -lnameprimären Dienstprogramm of findsymbolische Links nach ihrem Ziel zuordnen und readlinkden Inhalt des Links lesen. Ungetestet:

find /mnt/home/someone/something -lname '/home/someone/*' \
     -exec sh -c 'ln -snf "/mnt$(readlink "$0")" "$0"' {} \;

Es wäre besser, diese symbolischen Verknüpfungen relativ zu machen. Es gibt ein praktisches kleines Hilfsprogramm namens symlinks(ursprünglich von Mark Lords, jetzt von J. Brandt Buckley gepflegt), das in vielen Linux-Distributionen enthalten ist. Führen Sie vor dem Verschieben oder nach dem Wiederherstellen gültiger Links wie oben aus, symlinks -c /mnt/home/someone/somethingum alle absoluten Symlinks im angegebenen Verzeichnis in relative Symlinks zu konvertieren, es sei denn, sie überschreiten eine Dateisystemgrenze.

Gilles 'SO - hör auf böse zu sein'
quelle
Keine Beleidigung, dies ist ein großartiger Einzeiler, aber Bashs Saitensubstitution könnte wahrscheinlich etwas Magie bewirken, wenn sich der Pfad ändert, und wäre einfacher.
0xC0000022L
@STATUS_ACCESS_DENIED Wie so? Die einzige Zeichenfolgeoperation ist das Voranstellen /mnteines Pfads. Sie brauchen keine schickere Zeichenfolge als Verkettung.
Gilles 'SO- hör auf böse zu sein'
@ Gilles: Entschuldigung, ich habe mehr über deine Bemerkung mit den relativen Pfaden nachgedacht. Für eine genaue "Übersetzung" Ihres Beispiels haben Sie natürlich Recht.
0xC0000022L
13

Ich weiß, dass dies nicht genau das ist, was der Autor verlangt, aber es scheint, dass sie bereits ihre Antwort haben, also füge ich dies für andere wie mich hinzu, die über die Frage stolpern.

Das Folgende sollte helfen, wenn eine flexiblere Lösung erforderlich ist, z. B. eine Reihe defekter symbolischer Verknüpfungen, die durch Ersetzen eines Teils der Ziele der symbolischen Verknüpfung behoben werden können.

z.B. Nach einer Änderung des Benutzernamens, um den alten Benutzernamen durch den neuen Benutzernamen im Ziel vieler Links zu ersetzen, nachdem der Umzug bereits durchgeführt wurde. Erstellen Sie ein Skript mit dem Namen replace-simlinks (siehe unten):

#!/bin/bash
link=$1
# grab the target of the old link
target=$(readlink -- "$1")

# replace the first occurrence of oldusername with newusername in the target string
target=${target/oldusername/newusername}

# Test the link creation
echo ln -s -- "$target" "$link"

# If the above echo shows the correct commands are being issued, then uncomment the following lines and run the command again
#rm $link
#ln -s "$target" "$link"

und rufe es mit dem folgenden Befehl auf:

find /home/newusername/ -lname '/home/oldusername/*' -exec ~/bin/replace-simlinks {} \;

Hoffe das hilft jemandem

edit: Vielen Dank an Gilles für den Kickstart zu diesem Skript und den Tipp zur Verwendung des symlinks-Skripts, um die Links relativ zu machen.

Gerry
quelle
1
Ich finde diese Lösung besser, weil sie ein Ersetzen von Zeichenfolgen verwendet, was in Fällen hilfreich ist, in denen Sie den Namen eines Ordners in der Mitte des Pfads ändern müssen. Die Lösung ist auch recht einfach zu modifizieren, um bei Bedarf komplexere Transformationen durchzuführen.
Gallaecio
Ich würde empfehlen, die Argumente für die Zeichenfolgensubstitution in Anführungszeichen zu setzen, da dies erforderlich ist, um Schrägstriche zu verwenden, z. B. für den Pfad in der Frage des OP. target=${target/"/home"/"/mnt/home"}Sehr hilfreich. Vielen Dank.
Walter Nissen
3

/homeAls Symlink zu erstellen /mnt/home, und alle vorhandenen Symlinks sind wieder gültig.

Keith Thompson
quelle
2
Bind-Montag neigt oft zu weniger zerbrechlich als Symlinks in Szenarien , in denen Programme bewusst Symlinks sind und anders handeln , je nach der Tatsache , ...
0xC0000022L