Ich habe eine Reihe symbolischer Links zu einem anderen Laufwerk. Ich muss alle Dateien von diesem Laufwerk verschieben, auf die an anderer Stelle verwiesen wird, damit ich sie entfernen kann.
Marty Trenouth
Antworten:
14
Für einige Definitionen von "einfach":
#!/bin/shset-e
for link;do
test -h "$link"||continue
dir=$(dirname "$link")
reltarget=$(readlink "$link")case $reltarget in/*) abstarget=$reltarget;;*) abstarget=$dir/$reltarget;;esac
rm -fv "$link"
cp -afv "$abstarget""$link"||{# on failure, restore the symlink
rm -rfv "$link"
ln -sfv "$reltarget""$link"}done
Führen Sie dieses Skript mit Linknamen als Argumente aus, z. B. durch find . -type l -exec /path/tos/script {} +
Vielen Dank für die Bearbeitung, anon, aber das Skript tut Griff Dateinamen mit Leerzeichen ganz gut, von Variablen in allen erforderlichen Stellen zitieren. Der Wechsel "$var"zu "${var}"ist ein Noop in sh / bash. Ich habe den einen Bashismus ( [[) entfernt, der Rest ist mit POSIX sh kompatibel.
Grawity
Eine noch robustere Methode zur Behandlung von Symlink-Fehlern besteht darin cp, eine temporäre Datei im selben Verzeichnis wie mv -fdie temporäre Datei im Original zu speichern. Dies sollte vor Problemen schützen, wie das Niederhalten von Personen Ctrl-Coder das Auffüllen des Dateisystems zwischen den Befehlen rmund cp(wodurch verhindert wird, dass auch die neuen Befehle lnfunktionieren). Temporäre Dateinamen können ls -abei Bedarf für eine spätere Bereinigung leicht erkannt werden.
Herr Fooz
Als Randnotiz kann ich mich ernsthaft nicht erinnern, warum ich nicht nur abstarget=$(readlink -f "$link")den Case- Block verwendet habe, sondern möglicherweise auch aus Gründen der Portabilität.
Grawity
17
Könnte einfacher sein, einfach tar zu verwenden, um die Daten in ein neues Verzeichnis zu kopieren.
-H (c and r mode only)Symbolic links named on the command line will
be followed; the target of the link will be archived, not the
link itself.
Sie könnten so etwas gebrauchen
tar -hcf - sourcedir | tar -xf --C newdir
tar --help:-H,--format=FORMAT create archive of the given format
-h,--dereference follow symlinks; archive and dump the files they point to
Danke - fast das, was ich brauchte: Ich musste etwas tun wie: cp -L files tmp/ && rm files && cp tmp/files . Wenn Sie klarstellen, werden Sie wahrscheinlich mehr Menschen helfen ...
Salbei
5
"easy" wird höchstwahrscheinlich eine Funktion von Ihnen sein.
Ich würde wahrscheinlich ein Skript schreiben, das das Befehlszeilendienstprogramm "find" verwendet, um symbolisch verknüpfte Dateien zu finden, und dann rm und cp aufrufen, um die Datei zu entfernen und zu ersetzen. Es ist wahrscheinlich eine gute Idee, die Aktion von find überprüfen zu lassen, ob noch genügend freier Speicherplatz vorhanden ist, bevor Sie auch den Sym-Link verschieben.
Eine andere Lösung könnte darin bestehen, das fragliche Dateisystem durch etwas zu mounten, das die Sym-Links verbirgt (wie Samba), und dann einfach alles daraus zu kopieren. Aber in vielen Fällen würde so etwas andere Probleme mit sich bringen.
Eine direktere Antwort auf Ihre Frage lautet wahrscheinlich "Ja".
Bearbeiten: Gemäß der Anfrage für genauere Informationen. Laut der man-Seite für find listet dieser Befehl alle sym link-Dateien in einer Tiefe von 2 Verzeichnissen auf, von /:
find /-maxdepth 2-type l -exec ./ReplaceSymLink.sh {} \;
Ich glaube, das ruft ein Skript auf, das ich gerade erstellt habe, und übergibt den Dateinamen, den Sie gerade gefunden haben. Alternativ können Sie die Ausgabe der Suche in eine Datei erfassen (verwenden Sie "find [blah]> symlinks.data" usw.) und diese Datei dann an ein Skript übergeben, das Sie geschrieben haben, um ordnungsgemäß über das Original zu kopieren.
? Ein bisschen generisch - können Sie das näher erläutern?
Linker3000
2
Die Syntax lautet-exec ./ReplaceSymLink.sh {} \;
grawity
Hier finden Sie die Artikel und der als Antwort markierte wird verwendet, um die Links zu ersetzen!
Marty Trenouth
3
Dies ist der von mir verwendete Oneliner: Nehmen wir an, dass alle lokalen Dateien Links zu einer anderen Datei in "source" sind. Sie können die Dateiauswahl mit Mustern oder "Suchen" verfeinern. Bitte vor Gebrauch verstehen.
für f in *; do cp --remove-destination source / $ f $ f; getan
wie wäre es mit readlink: für f in *; do cp ---- remove-destination "$ (readlink $ f)" "$ f"; erledigt
Diego
Ja, das ist eine gute Idee, aber Sie verlieren die Kontrolle über den Vorgang. Eine Einschränkung meiner Lösung ist, dass sie nicht für Dateien mit Leerzeichen in der Mitte oder für sehr lange Listen funktioniert. Wahrscheinlich besteht die endgültige Lösung darin, den obigen Befehl 'find --exec' mit dem Befehl 'remove destination' zu kombinieren. Möchte jemand es versuchen?
MastroGeppetto
Leerzeichen in der Mitte sollten durch Anführungszeichen "$ f" ausgeglichen werden. So verwende ich es mit "find & xargs" anstelle von "for loop": find ./ -type l -print0 | xargs -0 -n1 -i sh -c 'cp --remove-destination $ (readlink "{ } ")" {} "'Ich habe es als separate Antwort für die Sichtbarkeit gepostet. superuser.com/a/1329543/499386
Diego
2
find .-type l -exec cp --dereference --recursive '{}''{}'.dereferenced \;
Erstellt eine Kopie jeder verknüpften Datei / jedes verknüpften Ordners <filename>.dereferenced, was sicherer ist (wenn es nicht so einfach ist), als sie nur direkt zu ersetzen. Das Verschieben der kopierten Daten in die Dateinamen der Symlinks wird dem Leser als Übung überlassen.
Eine kleine Verbesserung hilft, symbolische Links zu finden: für lnk in `find. -Typ l`; do src = $ (readlink $ lnk) && rm $ lnk && mv $ src $ lnk; getan (nicht mit Hierarchie getestet, Vorsicht mit Backticks)
Roman Susi
1
Ich hatte das gleiche Problem mit dem Kopieren von Links durch gwenview, wenn Sie normalerweise erwarten würden, dass es dem Link folgt und die Datei kopiert.
Was ich getan habe, um das Verzeichnis zu 'bereinigen', indem ich allen Links gefolgt bin und alle Dateien, auf die verwiesen wurde, in das Verzeichnis kopiert habe, war ein Arbeitsverzeichnis zu erstellen, z
"for file in `ls`; do cp -L $file scratchdir/$file; done; mv scratchdir/* ./"
Dies ist zu gefährlich, um ein Skript einzufügen, da es keine Überprüfung gibt, aber es hat mein Problem behoben.
Antworten:
Für einige Definitionen von "einfach":
Führen Sie dieses Skript mit Linknamen als Argumente aus, z. B. durch
find . -type l -exec /path/tos/script {} +
quelle
"$var"
zu"${var}"
ist ein Noop in sh / bash. Ich habe den einen Bashismus ([[
) entfernt, der Rest ist mit POSIX sh kompatibel.cp
, eine temporäre Datei im selben Verzeichnis wiemv -f
die temporäre Datei im Original zu speichern. Dies sollte vor Problemen schützen, wie das Niederhalten von PersonenCtrl-C
oder das Auffüllen des Dateisystems zwischen den Befehlenrm
undcp
(wodurch verhindert wird, dass auch die neuen Befehleln
funktionieren). Temporäre Dateinamen könnenls -a
bei Bedarf für eine spätere Bereinigung leicht erkannt werden.abstarget=$(readlink -f "$link")
den Case- Block verwendet habe, sondern möglicherweise auch aus Gründen der Portabilität.Könnte einfacher sein, einfach tar zu verwenden, um die Daten in ein neues Verzeichnis zu kopieren.
Sie könnten so etwas gebrauchen
quelle
tar -hcf - sourcedir | tar -xf - -C newdir
cp -L
ist die einfachere Lösungcp
Implementierungen kopieren Verzeichnisse.Wenn ich Sie richtig verstanden habe, sollte das
-L
Flag descp
Befehls genau das tun, was Sie wollen.Kopieren Sie einfach alle Symlinks und sie werden durch die Dateien ersetzt, auf die sie zeigen.
quelle
cp -L files tmp/ && rm files && cp tmp/files .
Wenn Sie klarstellen, werden Sie wahrscheinlich mehr Menschen helfen ..."easy" wird höchstwahrscheinlich eine Funktion von Ihnen sein.
Ich würde wahrscheinlich ein Skript schreiben, das das Befehlszeilendienstprogramm "find" verwendet, um symbolisch verknüpfte Dateien zu finden, und dann rm und cp aufrufen, um die Datei zu entfernen und zu ersetzen. Es ist wahrscheinlich eine gute Idee, die Aktion von find überprüfen zu lassen, ob noch genügend freier Speicherplatz vorhanden ist, bevor Sie auch den Sym-Link verschieben.
Eine andere Lösung könnte darin bestehen, das fragliche Dateisystem durch etwas zu mounten, das die Sym-Links verbirgt (wie Samba), und dann einfach alles daraus zu kopieren. Aber in vielen Fällen würde so etwas andere Probleme mit sich bringen.
Eine direktere Antwort auf Ihre Frage lautet wahrscheinlich "Ja".
Bearbeiten: Gemäß der Anfrage für genauere Informationen. Laut der man-Seite für find listet dieser Befehl alle sym link-Dateien in einer Tiefe von 2 Verzeichnissen auf, von /:
( dies wurde hier gefunden )
Um find zu bekommen, führen Sie etwas aus:
Ich glaube, das ruft ein Skript auf, das ich gerade erstellt habe, und übergibt den Dateinamen, den Sie gerade gefunden haben. Alternativ können Sie die Ausgabe der Suche in eine Datei erfassen (verwenden Sie "find [blah]> symlinks.data" usw.) und diese Datei dann an ein Skript übergeben, das Sie geschrieben haben, um ordnungsgemäß über das Original zu kopieren.
quelle
-exec ./ReplaceSymLink.sh {} \;
Dies ist der von mir verwendete Oneliner: Nehmen wir an, dass alle lokalen Dateien Links zu einer anderen Datei in "source" sind. Sie können die Dateiauswahl mit Mustern oder "Suchen" verfeinern. Bitte vor Gebrauch verstehen.
Hoffe das hilft
quelle
Erstellt eine Kopie jeder verknüpften Datei / jedes verknüpften Ordners
<filename>.dereferenced
, was sicherer ist (wenn es nicht so einfach ist), als sie nur direkt zu ersetzen. Das Verschieben der kopierten Daten in die Dateinamen der Symlinks wird dem Leser als Übung überlassen.quelle
Unter Verwendung einiger der vorherigen Ideen ersetzt der folgende Befehl rekursiv jeden Symlink durch eine Kopie des Originals:
quelle
basierend auf https://superuser.com/a/1301199/499386 von MastroGeppetto
quelle
Es gibt viele gute Antworten, aber ich habe seitdem nach etwas Leichtem gesucht
quelle
Ich hatte das gleiche Problem mit dem Kopieren von Links durch gwenview, wenn Sie normalerweise erwarten würden, dass es dem Link folgt und die Datei kopiert.
Was ich getan habe, um das Verzeichnis zu 'bereinigen', indem ich allen Links gefolgt bin und alle Dateien, auf die verwiesen wurde, in das Verzeichnis kopiert habe, war ein Arbeitsverzeichnis zu erstellen, z
Dies ist zu gefährlich, um ein Skript einzufügen, da es keine Überprüfung gibt, aber es hat mein Problem behoben.
quelle
quelle
Ich habe eine einzeilige Version gemacht, da mein Web-Hotel keine Bash-Skripte erlaubte und es für mich gut funktionierte:
quelle