Gibt es eine einfache Möglichkeit, alle symbolischen Links durch die Datei zu ersetzen, mit der sie verknüpft sind?
Gibt es eine einfache Möglichkeit, alle symbolischen Links durch die Datei zu ersetzen, mit der sie verknüpft sind?
Antworten:
Für einige Definitionen von "einfach":
#!/bin/sh
set -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 {} +
"$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 wie mv -f
die temporäre Datei im Original zu speichern. Dies sollte vor Problemen schützen, wie das Niederhalten von Personen Ctrl-C
oder das Auffüllen des Dateisystems zwischen den Befehlen rm
und cp
(wodurch verhindert wird, dass auch die neuen Befehle ln
funktionieren). Temporäre Dateinamen können ls -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.
-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
tar -hcf - sourcedir | tar -xf - -C newdir
cp -L
ist die einfachere Lösung
cp
Implementierungen kopieren Verzeichnisse.
Wenn ich Sie richtig verstanden habe, sollte das -L
Flag des cp
Befehls genau das tun, was Sie wollen.
Kopieren Sie einfach alle Symlinks und sie werden durch die Dateien ersetzt, auf die sie zeigen.
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 /:
find / -maxdepth 2 -type l -print
Um find zu bekommen, führen Sie etwas aus:
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.
-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.
für f in *; do cp --remove-destination source / $ f $ f; getan
Hoffe das hilft
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.
find ./ -type l -print0|xargs -0 -n1 -i sh -c 'cp --remove-destination $(readlink "{}") "{}" '
basierend auf https://superuser.com/a/1301199/499386 von MastroGeppetto
Es gibt viele gute Antworten, aber ich habe seitdem nach etwas Leichtem gesucht
for i in *; do link=$(readlink $i) && rm $i && mv $link $i; done
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.
for f in *; do cp --remove-destination $(readlink "$f") "$f"; done
Ich habe eine einzeilige Version gemacht, da mein Web-Hotel keine Bash-Skripte erlaubte und es für mich gut funktionierte:
before:
> find . -type l | wc -l
358
> for link in `find . -type l` ; do echo "$link : "; ls -al $link ; cp $link notalink; unlink $link; mv notalink $link ; ls -al $link; done
...
after:
> find . -type l | wc -l
0