Aggiornamento simbolico dei collegamenti simbolici in modo ricorsivo


12

Ho un'app Web che ha un sacco di collegamenti simbolici nelle sottodirectory. Devo spostare l'app in un'altra struttura di directory e devo aggiornare tutti i collegamenti simbolici per puntare al nuovo percorso. Per esempio:

Old Dir: /home/user/public_html/dev
New Dir: /home/user/public_html/qa
Old Symlink: /home/user/public_html/qa/multisites/slave01/images -> /home/user/public_html/dev/images
New Symlink:/home/user/public_html/qa/multisites/slave01/images -> /home/user/public_html/qa/images

Il problema è che ce ne sono molti sparsi in varie directory. Come posso cercare ricorsivamente dalla radice e ricreare tutti i collegamenti simbolici che puntano a /dev/con /qa/?

Risposte:


16

Questo comando bash dovrebbe farlo per te:

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

Usa findper identificare tutti i file nella qadirectory che sono collegamenti simbolici con una destinazione che si trova nella devdirectory e per ognuno, stampa un comando bash che sostituirà il collegamento con un collegamento al percorso equivalente in qa/. Dopo aver eseguito questo, basta eseguire lo script generato con

bash script.sh

Potresti prima esaminarlo manualmente per assicurarti che abbia funzionato.

Ecco una versione più dettagliata del findcomando sopra per una lettura più semplice (anche se non lo scriverei necessariamente in questo modo in pratica):

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

Questo crea uno script.sh vuoto. Ed eseguendo il comando find in questo modo: find /home/user/public_html/qa/ -type l -lname '/home/user/public_html/dev/*' non genera nulla.
ggutenberg,

Ti sei ricordato di cambiare i percorsi a quelli reali sul tuo filesystem, giusto? Cosa succede se corri solo find /home/usr/public_html/qa/ -type l? Se questo non trova i collegamenti, sta succedendo qualcosa di molto strano nel tuo sistema.
David Z,

Sì, " find /home/user/public_html/qa/ -type l" genera i collegamenti. Ma aggiungendo il parametro -lname non viene prodotto nulla.
ggutenberg,

In realtà, su ulteriori test sembra che funzioni. Non sono sicuro di cosa stavo facendo di sbagliato ieri, ma ora sembra ok. Grazie.
ggutenberg,

Eh, strano. Bene, se hai mai capito cosa non andava, metti un commento qui. Sono curioso.
David Z,

5

Nel caso in cui qualcun altro lo trovi durante la ricerca di una soluzione: crea un file chiamato "linkmod.sh" contenente:

#!/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"

e corri

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

Puoi spesso usare l'opzione -lname in find se necessario.

NOTA: devi usare 2x \ nei motivi prima di ogni carattere che richiede \ in sed, poiché l'eco ne rimuove uno. Per esempio

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

Rimuovere il echodall'ultima riga se i comandi ln sono corretti.


Potrebbe essere utile chiarire che sia echonell'ultima riga dello script sia echonel find .. | xargs .. linkmod.sh ...comando stesso devono essere rimossi entrambi .
Kyle Strand,

2

Ho creato uno script bash link_rename.shper la ridenominazione ricorsiva di collegamenti simbolici in una determinata directory

#! /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)

Può essere eseguito come link_rename.sh /home/human/dir link1 link2

Lo script ha 3 argomenti:

  1. La directory in cui si desidera eseguire la ridenominazione batch dei collegamenti simbolici
  2. Il vecchio modello. Ecco link1il vecchio schema che verrà sostituito
  3. Il nuovo modello. Ecco link2il nuovo modello con il quale link1verrà sostituito

Lo script legge ricorsivamente tutti i collegamenti simbolici nella directory usando find "$DIR" -type l ed elabora riga per riga.

$line è il collegamento simbolico che deve essere rinominato

CUR_LINK_PATH è il vecchio percorso

NEW_LINK_PATH si ottiene eseguendo la sostituzione della stringa nel vecchio percorso del collegamento.

Il vecchio symlink viene rimosso e il nuovo symlink viene creato usando ln -s "$NEW_LINK_PATH" "$line"


0

Ho finito per scrivere uno script PHP a riga di comando che sembra fare il trucco.

<?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";
            }
        }
    }
}
?>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.