Batch Update Symbolische Links rekursiv

11

Ich habe eine Web-App, die eine Reihe symbolischer Links in Unterverzeichnissen enthält. Ich muss die App in eine andere Verzeichnisstruktur verschieben und alle Symlinks aktualisieren, um auf den neuen Pfad zu verweisen. Zum Beispiel:

Altes Dir: /home/user/public_html/dev
Neues Dir: /home/user/public_html/qa
Altes Symlink: /home/user/public_html/qa/multisites/slave01/images -> /home/user/public_html/dev/images
Neues Symlink:/home/user/public_html/qa/multisites/slave01/images -> /home/user/public_html/qa/images

Das Problem ist, dass viele davon in verschiedenen Verzeichnissen verstreut sind. Wie kann ich rekursiv vom Stamm aus suchen und alle Symlinks neu erstellen, auf die /dev/mit verwiesen wird /qa/?

ggutenberg
quelle

Antworten:

15

Dieser Bash-Befehl sollte es für Sie tun:

find /home/user/public_html/qa/ -type l -lname '/home/user/public_html/dev/*' -printf 'ln -nsf "$(readlink "%p" | sed s/dev/qa/)" "$(echo "%p" | sed s/dev/qa/)"\n' > script.sh

Es verwendet find, um alle Dateien im qaVerzeichnis zu identifizieren, bei denen es sich um symbolische Verknüpfungen mit einem Ziel im devVerzeichnis handelt, und druckt für jede Datei einen Bash-Befehl aus, der die Verknüpfung durch eine Verknüpfung zum entsprechenden Pfad in ersetzt qa/. Nachdem Sie dies ausgeführt haben, führen Sie einfach das generierte Skript mit aus

bash script.sh

Möglicherweise möchten Sie es zuerst manuell überprüfen, um sicherzustellen, dass es funktioniert.

Hier ist eine ausführlichere Version des obigen findBefehls zum leichteren Lesen (obwohl ich ihn in der Praxis nicht unbedingt so schreiben würde):

SRC_DIR="/home/user/public_html/qa"
OLD_TARGET="/home/user/public_html/dev"
SUB="s/dev/qa/"

find $SRC_DIR -type l \
  -lname "$OLD_TARGET/*" -printf \
  'ln -nsf "$(readlink "%p"|sed $SUB)" "$(echo "%p"|sed $SUB)"\n'\
 > script.sh
David Z.
quelle
Dadurch wird eine leere script.sh erstellt. Und wenn Sie den Befehl find so find /home/user/public_html/qa/ -type l -lname '/home/user/public_html/dev/*' ausführen, wird nichts ausgegeben.
Ggutenberg
Sie haben daran gedacht, die Pfade auf die tatsächlichen in Ihrem Dateisystem zu ändern, oder? Was passiert, wenn Sie nur laufen find /home/usr/public_html/qa/ -type l? Wenn das die Links nicht findet, passiert etwas sehr Seltsames mit Ihrem System.
David Z
Ja, " find /home/user/public_html/qa/ -type l" gibt die Links aus. Durch Hinzufügen des Parameters -lname wird jedoch nichts ausgegeben.
Ggutenberg
Bei weiteren Tests sieht es tatsächlich so aus, als würde dies funktionieren. Ich bin mir nicht sicher, was ich gestern falsch gemacht habe, aber jetzt scheint es in Ordnung zu sein. Vielen Dank.
Ggutenberg
Huh, komisch. Wenn Sie jemals herausfinden, was schief gelaufen ist, geben Sie hier einen Kommentar ein. Ich bin neugierig.
David Z
5

Falls jemand anderes dies bei der Suche nach einer Lösung findet: Erstellen Sie eine Datei mit dem Namen "linkmod.sh", die Folgendes enthält:

#!/bin/sh
PATTERN1=`echo "$2"`
PATTERN2=`echo "$3"`
LINKNAME=`echo "$1"`
OLDTARGET=`readlink "$1"`
NEWTARGET=`echo "$OLDTARGET" \
| sed -e 's/'"$PATTERN1"'/'"$PATTERN2"'/'`
echo ln -nsf "$NEWTARGET" "$LINKNAME"

und Renn

find . -type l -print0 | xargs -0IX echo linkmod.sh X "pattern1" "pattern2"

Bei Bedarf können Sie die Option -lname in find verwenden.

HINWEIS: Sie müssen 2x \ in den Mustern vor allen Zeichen verwenden, für die \ in sed erforderlich ist, da das Echo eines entfernt. Zum Beispiel

find . -type l -print0 | xargs -0IX echo linkmod.sh X "folder\\ name\\/file" "folder2\\ name\\/file"

Entfernen Sie das echoaus der letzten Zeile, wenn die ln-Befehle korrekt sind.

rknC
quelle
Könnte gut sein , um klarzustellen , dass die beiden echoin der letzten Zeile des Skripts und der echoin dem find .. | xargs .. linkmod.sh ...Befehl selbst beide entfernt werden müssen.
Kyle Strand
2

Ich habe ein Bash-Skript link_rename.shfür das rekursive Umbenennen symbolischer Links in einem bestimmten Verzeichnis erstellt

#! /bin/bash

DIR=$1
OLD_PATTERN=$2
NEW_PATTERN=$3

while read -r line
do
    echo $line
    CUR_LINK_PATH="$(readlink "$line")"
    NEW_LINK_PATH="$CUR_LINK_PATH"  
    NEW_LINK_PATH="${NEW_LINK_PATH/"$OLD_PATTERN"/"$NEW_PATTERN"}"
    rm "$line"
    ln -s "$NEW_LINK_PATH" "$line"
done <<< $(find "$DIR" -type l)

Es kann ausgeführt werden als link_rename.sh /home/human/dir link1 link2

Das Skript hat 3 Argumente:

  1. Das Verzeichnis, in dem Sie die Batch-Umbenennung von Symlinks durchführen möchten
  2. Das alte Muster. Hier link1ist das alte Muster, das ersetzt wird
  3. Das neue Muster. Hier link2ist das neue Muster, durch das link1ersetzt wird

Das Skript liest rekursiv alle Symlinks im Verzeichnis find "$DIR" -type l und verarbeitet sie zeilenweise.

$line ist der Symlink, der umbenannt werden muss

CUR_LINK_PATH ist der alte Weg

NEW_LINK_PATH wird durch Ersetzen der Zeichenfolge im alten Verbindungspfad erhalten.

Der alte Symlink wird entfernt und mit wird ein neuer Symlink erstellt ln -s "$NEW_LINK_PATH" "$line"

Akhil Mohan
quelle
0

Am Ende habe ich ein Kommandozeilen-PHP-Skript geschrieben, das den Trick zu tun scheint.

<?php
//Run via command-line
$dir = new RecursiveDirectoryIterator('.');
foreach(new RecursiveIteratorIterator($dir) as $file) {
    //$link = readlink($file);
    if(is_link($file)) {
        $old_link = readlink($file);
        $new_link = str_ireplace("/joomla/", "/qa/", $old_link);
        if($new_link != $old_link) {
            exec('rm "'.$file.'"');
            exec('ln -fs "'.$new_link.'" "'.$file.'"');
            $new_link = readlink($file);
            if($new_link == $old_link) {
                echo $file."\t".$old_link."\t".$new_link."\n";
            }
        }
    }
}
?>
ggutenberg
quelle