Як я можу "перев'язати" багато розбитих символьних посилань?


54

У мене є дерево каталогів, яке містить безліч символічних посилань на файли під /home... однак, я перейшов /homeдо /mnt/homeі мені потрібен спосіб "повторно пов'язати" всі символьні посилання. Чи існує така функціональність чи мені потрібно написати сценарій для цього?

Як приклад, я маю щось таке:

[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

Я хочу команду, яка знайде всі символьні посилання та посилання на ті самі місця, але під /mnt/homeними/home

Чи існує така команда?

Відповіді:


55

Немає команди перевстановити символічне посилання, все, що ви можете зробити - це видалити його та створити ще одне. Якщо припустити, що у вас є утиліти GNU (наприклад, під невбудованим Linux або Cygwin), ви можете використовувати -lnameпервинні, findщоб зіставити символьні посилання за їх ціллю та readlinkпрочитати вміст посилання. Не перевірено:

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

Краще зробити ці символічні посилання відносними. Існує зручна маленька утиліта, яку називають symlinks(спочатку Марк Лордс, зараз її підтримує Дж. Брандт Баклі), яка присутня у багатьох дистрибутивах Linux. Перед переміщенням або після відновлення дійсних посилань, як зазначено вище, запустіть symlinks -c /mnt/home/someone/somethingдля перетворення всіх абсолютних посилань у вказаному каталозі у відносні символьні посилання, якщо вони не перетинають межу файлової системи.


Без образи, це чудовий однолінійний, але заміна рядка Баша, ймовірно, могла б зробити якусь магію, щоб змінити шлях і було б простіше.
0xC0000022L

@STATUS_ACCESS_DENIED Як так? Єдина струнна операція - /mntпередбачити шлях; вам не потрібна більш хитра струнна операція, ніж конкатенація.
Жил "ТАК - перестань бути злим"

@Gilles: вибачте, я більше думав про ваше зауваження щодо відносних шляхів. Точний "переклад" вашого прикладу ви, звичайно, праві.
0xC0000022L

13

Я знаю, що це не зовсім те, що запитує автор, але, здається, вони вже мають свою відповідь, тому я додаю це для інших, як я, які натрапляють на питання.

Далі слід допомогти, якщо потрібне більш гнучке рішення, наприклад, купа зламаних символьних посилань, які можна виправити, замінивши частину цілей символічного посилання.

напр. Після зміни імені користувача замінити старе ім’я користувача на нове ім'я користувача в цілі багатьох посилань після того, як переміщення вже було зроблено. Створіть скрипт, який називається заміна-посилання, показаний нижче:

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

і зателефонуйте за допомогою наступної команди:

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

Сподіваюся, це допоможе комусь

редагувати: Дякую Жиллу за старт цього сценарію та підказку щодо використання сценарію символьних посилань, щоб зробити посилання відносними.


1
Я вважаю це рішення кращим, оскільки воно використовує заміну рядка, що допомагає у випадках, коли вам доведеться змінити назву папки посеред шляху. Рішення також досить легко модифікувати для виконання більш складних перетворень, якщо потрібно.
Gallaecio

Я рекомендую навести аргументи для підстановки рядків, оскільки це необхідно зробити для використання косої риси, наприклад, для шляху в питанні про ОП. target=${target/"/home"/"/mnt/home"}Дуже корисно, хоча. Дякую.
Вальтер Ніссен

3

Створіть /homeяк посилання на /mnt/home, і всі існуючі символьні посилання знову будуть дійсними.


2
Монтаж прив’язки часто має тенденцію бути менш крихким, ніж символьні посилання в сценаріях, коли програми знають про посилання та діють по-різному залежно від факту ...
0xC0000022L
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.