Konvertieren Sie Symlinks in Hardlinks

25

Ich möchte rekursiv Softlinks in Hardlinks in einem Verzeichnis konvertieren. Ich habe so etwas ausprobiert:

for f in *; do (mv $f{,~} && ln $(readlink $f~) && rm $f~) done

… Aber es gibt zwei Hauptprobleme:

  • nicht rekursiv
  • nimmt Dateien auf, die keine symbolischen Verknüpfungen sind

Es wäre schön, die obige Zeile irgendwie zu füttern find -type l, aber ich bin mir nicht sicher, wie ich das machen soll.

Attila O.
quelle
1
Siehe auch [diese Diskussion] [1] ( cp -aH). [1]: unix.stackexchange.com/questions/94185/…
Michael Shigorin

Antworten:

34

Dieser Befehl sollte funktionieren:

find -type l -exec bash -c 'ln -f "$(readlink -m "$0")" "$0"' {} \;

Wie es funktioniert:

  • find -type l findet alle Links im aktuellen Verzeichnis.

  • -exec bash -c '...' {} \;ruft bash zur Ausführung auf ....

    Es übergibt {}- den Namen des Links, der gerade verarbeitet wird - als Argument, auf das die Bash zugreifen kann $0.

  • readlink -m "$0" Gibt den absoluten Pfad des Ziels der symbolischen Verknüpfung zurück.

  • ln -f "$(readlink -m "$0")" "$0"überschreibt ( -f) den symbolischen Link $0mit einem festen Link zu seinem Ziel.

Wenn der Link aus irgendeinem Grund nicht konvertiert werden kann, bleibt er unberührt und ln gibt eine Fehlermeldung aus.

Dennis
quelle
Wäre es in Bezug auf diesen letzten Absatz nicht ausreichend, absolute Pfade zu bashund anzugeben ln?
Daniel Beck
2
Mein Problem war, dass readlink standardmäßig einen relativen Pfad zurückgibt, aber der -eSchalter behebt das.
Dennis
Was wäre der Befehl für OSX?
Igor Markelov
@IgorMarkelov Es tut mir leid, aber ich habe keine Ahnung, wenn es um OSX geht.
Dennis
1
Auf einem Mac ist es: brew install coreutilsund find * -type l -exec bash -c 'ln -f "$(greadlink -m "$0")" "$0"' {} \;.
Igor Markelov