Jak mogę „ponownie połączyć” wiele zepsutych dowiązań symbolicznych?

54

Mam drzewo katalogów, które zawiera kilka dowiązań symbolicznych do plików pod /home... jednak przeniosłem /homesię /mnt/homei potrzebuję sposobu, aby "ponownie połączyć" wszystkie dowiązania symboliczne. Czy taka funkcjonalność istnieje, czy muszę napisać skrypt, aby to zrobić?

Na przykład mam coś takiego:

[root@trees ~]# ls -l /mnt/home/someone/something
total 4264
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 a -> /home/someone/someotherthing/a
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 b -> /home/someone/someotherthing/b
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 c -> /home/someone/someotherthing/c
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 d -> /home/someone/someotherthing/d
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 e -> /home/someone/someotherthing/e

/mnt/home/someone/something/subdir:
total 4264
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 a -> /home/someone/someotherthing/subdir/a
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 b -> /home/someone/someotherthing/subdir/b
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 c -> /home/someone/someotherthing/subdir/c
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 d -> /home/someone/someotherthing/subdir/d
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 e -> /home/someone/someotherthing/subdir/e

Chcę polecenia, które znajdzie wszystkie dowiązania symboliczne i połączy się ponownie w tych samych miejscach, ale pod nimi /mnt/homezamiast/home

Czy takie polecenie istnieje?

Josh
źródło

Odpowiedzi:

55

Nie ma polecenia przekierowania dowiązania symbolicznego, wystarczy usunąć go i utworzyć kolejne. Zakładając, że masz narzędzia GNU (np. Pod niewbudowanym Linuksem lub Cygwinem), możesz użyć elementu -lnamepodstawowego z, findaby dopasować dowiązania symboliczne według ich celu i readlinkodczytać zawartość łącza. Niesprawdzone:

find /mnt/home/someone/something -lname '/home/someone/*' \
     -exec sh -c 'ln -snf "/mnt$(readlink "$0")" "$0"' {} \;

Lepiej byłoby uczynić te linki symboliczne względnymi. Istnieje wygodne małe narzędzie o nazwie symlinks(pierwotnie Mark Lords, obecnie utrzymywane przez J. Brandta Buckleya), obecne w wielu dystrybucjach Linuksa. Przed przeniesieniem lub po przywróceniu prawidłowych łączy, jak wyżej, uruchom, symlinks -c /mnt/home/someone/somethingaby przekonwertować wszystkie bezwzględne dowiązania symboliczne w określonym katalogu na względne dowiązania symboliczne, chyba że przekroczą one granicę systemu plików.

Gilles „SO- przestań być zły”
źródło
Bez obrazy, jest to świetny jednoliniowy, ale zamiana sznurka Basha może prawdopodobnie trochę magii zmienić ścieżkę i byłoby łatwiej.
0xC0000022L
@STATUS_ACCESS_DENIED Jak to zrobić? Jedyną operacją na łańcuchach jest poprzedzenie /mntścieżki; nie potrzebujesz bardziej wyszukanej operacji na łańcuchach niż konkatenacja.
Gilles „SO- przestań być zły”
@Gilles: przepraszam, myślałem więcej o twojej uwadze ze względnymi ścieżkami. Dokładne „tłumaczenie” twojego przykładu ma oczywiście rację.
0xC0000022L
13

Wiem, że nie jest to dokładnie to, o co prosi autor, ale wygląda na to, że mają już swoją odpowiedź, więc dodaję to dla innych, takich jak ja, którzy natkną się na pytanie.

Poniższe informacje powinny pomóc, jeśli wymagane jest bardziej elastyczne rozwiązanie, takie jak wiązka zepsutych łączy symbolicznych, które można naprawić, zastępując część elementów docelowych łącza symbolicznego.

na przykład. Po zmianie nazwy użytkownika, aby zastąpić starą nazwę użytkownika nową nazwą użytkownika w miejscu docelowym wielu łączy, po przeprowadzeniu przenoszenia. Utwórz skrypt o nazwie replace-simlinks pokazany poniżej:

#!/bin/bash
link=$1
# grab the target of the old link
target=$(readlink -- "$1")

# replace the first occurrence of oldusername with newusername in the target string
target=${target/oldusername/newusername}

# Test the link creation
echo ln -s -- "$target" "$link"

# If the above echo shows the correct commands are being issued, then uncomment the following lines and run the command again
#rm $link
#ln -s "$target" "$link"

i wywołaj go za pomocą następującego polecenia:

find /home/newusername/ -lname '/home/oldusername/*' -exec ~/bin/replace-simlinks {} \;

Mam nadzieję, że komuś to pomoże

edytuj: Dzięki Gilles za rozpoczęcie tego skryptu i wskazówkę dotyczącą używania skryptu dowiązań symbolicznych, aby linki były względne.

Gerry
źródło
1
Znalazłem to rozwiązanie lepiej, ponieważ używa ono zamiany łańcucha, co pomaga w przypadkach, w których musisz zmienić nazwę folderu na środku ścieżki. Rozwiązanie jest również dość łatwe do zmodyfikowania, aby w razie potrzeby przeprowadzić bardziej złożone transformacje.
Gallaecio
Polecam zacytowanie argumentów na podstawienie ciągu, ponieważ należy to zrobić, aby użyć ukośników, np. Ścieżki w pytaniu PO. target=${target/"/home"/"/mnt/home"}Jednak bardzo pomocne. Dzięki.
Walter Nissen
3

Utwórz /homejako dowiązanie symboliczne /mnt/home, a wszystkie istniejące dowiązania symboliczne znów będą ważne.

Keith Thompson
źródło
2
Montowanie powiązań często bywa mniej kruche niż dowiązania symboliczne w scenariuszach, w których programy są świadome dowiązań symbolicznych i działają inaczej w zależności od faktu ...
0xC0000022L