Как изменить путь символической ссылки для многих файлов?
Мне было изменено имя каталога. В этом каталоге тысячи файлов. Некоторые проекты используют эти файлы, в проектах есть символические ссылки.
- Как найти все символические ссылки, которые имеют имя папки в своем адресе?
- как изменить все эти символические ссылки на другой путь в автоматическом режиме?
если 2 только скрипты bash с удалением и созданием нового - я сделаю это, но может быть вы знаете более простой способ?
1 ответ
Это немного сложно, но это может быть сделано с
find
,readlink
проверка, чтобы проверить, является ли символическая ссылка относительной или нет, иsed
избавиться от..
в путевых именах (скопировано 1:1 из этого ответа).
(Обратите внимание, что наиболее удобные методы (такие какreadlink -f
) недоступны из-за того, что цели символических ссылок больше не существуют.)
Предполагая, что ваш старый путь/var/lib/old/path
:oldpath='/var/lib/old/path'; find / -type l -execdir bash -c 'p="$(readlink "{}")"; if [ "${p:0:1}" != "/" ]; then p="$(echo "$(pwd)/$p" | sed -e "s|/\./|/|g" -e ":a" -e "s|/[^/]*/\.\./|/|" -e "t a")"; fi; if [ "${p:0:'${#oldpath}'}" == "'"$oldpath"'" ]; then ...; fi;' \;
Теперь замените
...
сверху сln -sf
(-f
переопределить существующую ссылку).
Предполагая, что ваш новый путь/usr/local/my/awesome/new/path
:oldpath='/var/lib/old/path'; newpath='/usr/local/my/awesome/new/path'; find / -type l -execdir bash -c 'p="$(readlink "{}")"; if [ "${p:0:1}" != "/" ]; then p="$(echo "$(pwd)/$p" | sed -e "s|/\./|/|g" -e ":a" -e "s|/[^/]*/\.\./|/|" -e "t a")"; fi; if [ "${p:0:'${#oldpath}'}" == "'"$oldpath"'" ]; then ln -sf "'"$newpath"'${p:'${#oldpath}'}" "{}"; fi;' \;
Обратите внимание, что oldpath
а также newpath
должны быть абсолютные пути.
Также обратите внимание, что это преобразует все относительные символические ссылки в абсолютные.
Можно было бы сохранить их относительными, но только с большими усилиями.
Ломать его
Для тех из вас, кому небезразлично, что на самом деле означает это однострочный:
find
- классный исполняемый файл/
- где искать, в данном случае системный рут-type l
- сопоставить символические ссылки-execdir
- для каждого совпадения выполните следующую команду в каталоге соответствующего файла:bash
- хорошо, баш-c
- выполнить следующую строку (начальная и конечная'
удалены):p="$(readlink "{}")";
- начиная с самого внутреннего:"
- начать строку, чтобы убедиться, что расширение не происходит{}
- заполнитель для имени совпадающего файла (особенность-execdir
)"
- конец строкиreadlink ...
- узнать, куда указывает символическая ссылкаp="$(...)"
- и сохранить результат в$p
if [ "${p:0:1}" != "/" ]; then
- если первый символ$p
является/
(т.е. символическая ссылка является абсолютной), затем...p="$(echo "$(pwd)/$p" | sed -e "s|/\./|/|g" -e ":a" -e "s|/[^/]*/\.\./|/|" -e "t a")";
- преобразовать путь в абсолютный:$(pwd)
- текущий каталог (где находится соответствующий файл, потому что мы используем-execdir
)/$p
- добавить косую черту и цель символической ссылки к пути рабочего каталогаecho "$(pwd)/$p" |
- передать вышеприведенное к следующей командеsed ...
- разрешить все..
смотри здесьp="$(...)"
и сохранить результат обратно в$p
,
fi;
- конецif
if [ "${p:0:'${#oldpath}'}" == "'"$oldpath"'" ];
- если$p
начинается с$oldpath
${p:0:'${#oldpath}'}
- подстрока$p
начиная с позиции0
с длиной$oldpath
:${#oldpath}
- длина переменной$oldpath
'...'
- требуется, потому что мы внутри'
строка в кавычках
then
- затем...ln -sf
- связать символически и переопределить существующий файл с аргументами:"'"$newpath"'${p:'${#oldpath}'}"
- заменить$oldpath
часть$p
с$newpath
(фактически удалить столько символов из$p
как$oldpath
долго и готов$newpath
к нему)"
- начать строку'
- конец'
аргументbash -c
"
- добавить"
-строка к нему (в которой происходит расширение переменной), содержащая:$newpath
- значение$newpath
"
- конец"
аргументbash -c
'
- добавить'
-строка к нему, содержащая:${p:
- подстрокаp
, начинается с:'
- закончить аргументbash -c
${#oldpath}
- добавить длину$oldpath
к этому'
- добавить другой'
к ней}
- конец подстроки"
- конец строки
"{}"
- файл ссылки, путь которого остается прежним
fi;
- конецif
\;
- разделитель для-execdir