Batch Update Symboliczne linki Rekurencyjnie


13

Mam aplikację internetową, która zawiera wiele dowiązań symbolicznych w podkatalogach. Muszę przenieść aplikację do innej struktury katalogów i muszę zaktualizować wszystkie dowiązania symboliczne, aby wskazywały nową ścieżkę. Na przykład:

Stary katalog: /home/user/public_html/dev
Nowy katalog: /home/user/public_html/qa
Stary symbol: /home/user/public_html/qa/multisites/slave01/images -> /home/user/public_html/dev/images
Nowy symbol:/home/user/public_html/qa/multisites/slave01/images -> /home/user/public_html/qa/images

Problem polega na tym, że jest ich wiele w różnych katalogach. Jak mogę rekurencyjnie wyszukiwać od katalogu głównego i ponownie tworzyć wszystkie dowiązania symboliczne wskazujące za /dev/pomocą /qa/?

Odpowiedzi:


17

To polecenie bash powinno to zrobić za Ciebie:

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

Służy finddo identyfikowania wszystkich plików w qakatalogu, które są dowiązaniami symbolicznymi, z celem znajdującym się w devkatalogu, i dla każdego z nich wypisuje polecenie bash, które zastąpi łącze linkiem do równoważnej ścieżki w qa/. Po uruchomieniu uruchom skrypt za pomocą

bash script.sh

Możesz najpierw sprawdzić to ręcznie, aby upewnić się, że zadziałało.

Oto bardziej szczegółowa wersja powyższego findpolecenia dla łatwiejszego czytania (choć niekoniecznie napisałabym to w praktyce):

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

To tworzy pusty skrypt.sh. Uruchomienie polecenia find w ten sposób: find /home/user/public_html/qa/ -type l -lname '/home/user/public_html/dev/*' nic nie wyświetla.
ggutenberg

Pamiętasz, jak zmienić ścieżki do rzeczywistych w systemie plików, prawda? Co się stanie, jeśli po prostu uciekniesz find /home/usr/public_html/qa/ -type l? Jeśli to nie znajdzie linków, w twoim systemie dzieje się coś bardzo dziwnego.
David Z

Tak, ” find /home/user/public_html/qa/ -type l” wyświetla linki. Ale dodanie parametru -lname niczego nie wyświetla.
ggutenberg

Właściwie po dalszych testach wygląda na to, że to działa. Nie jestem pewien, co robiłem wczoraj źle, ale wydaje się teraz w porządku. Dzięki.
ggutenberg

Hej, dziwne. Cóż, jeśli kiedykolwiek zorientujesz się, co poszło nie tak, napisz tutaj komentarz. Jestem ciekawy.
David Z

5

Jeśli ktoś inny znajdzie to podczas szukania rozwiązania: Utwórz plik o nazwie „linkmod.sh” zawierający:

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

i biegnij

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

W razie potrzeby możesz użyć opcji -lname w find.

UWAGA: musisz użyć 2x \ we wzorach przed dowolnymi znakami, które wymagają \ w sed, ponieważ echo usuwa jeden. Na przykład

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

Usuń echoostatni wiersz, jeśli polecenia ln są poprawne.


Może być dobre wyjaśnienie, że zarówno echow ostatnim wierszu skryptu oraz echow find .. | xargs .. linkmod.sh ...poleceniu samego obie muszą zostać usunięte.
Kyle Strand,

2

Stworzyłem skrypt bash link_rename.shdla rekurencyjnej zmiany nazw dowiązań symbolicznych w danym katalogu

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

Można go wykonać jako link_rename.sh /home/human/dir link1 link2

Skrypt ma 3 argumenty:

  1. Katalog, w którym chcesz wykonać wsadową zmianę nazwy dowiązań symbolicznych
  2. Stary wzór. Oto link1stary wzór, który zostanie zastąpiony
  3. Nowy wzór. Oto link2nowy wzór, który link1zostanie zastąpiony

Skrypt rekurencyjnie odczytuje wszystkie dowiązania symboliczne w katalogu przy użyciu find "$DIR" -type l i przetwarza je wiersz po wierszu.

$line jest dowiązaniem symbolicznym, którego nazwę należy zmienić

CUR_LINK_PATH to stara ścieżka

NEW_LINK_PATH jest uzyskiwany przez wykonanie zamiany łańcucha na starej ścieżce łącza.

Stare symlink jest usuwane i nowe symlink jest tworzone przy użyciu ln -s "$NEW_LINK_PATH" "$line"


0

Skończyło się na napisaniu skryptu PHP w wierszu poleceń, który wydaje się załatwić sprawę.

<?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";
            }
        }
    }
}
?>
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.