Рейтинг:0

Как я могу искать символические ссылки, которые указывают на другие символические ссылки?

флаг ng

У меня есть болото связанных символических ссылок, разбросанных вокруг:

A (символическая ссылка) -> B (символическая ссылка) -> C (файл)

Некоторые могут даже включать более длинные цепочки, я еще не уверен.

При ручном изучении одного файла легко увидеть, что происходит, но я ищу автоматизированный способ найти их и (предпочтительно) очистить их.

В приведенном выше примере я бы хотел, чтобы символическая ссылка B->C оставалась на месте, но символическая ссылка A->B стала бы A->C.

Выявление их, если основная цель; количество может оказаться настолько низким, что исправить их вручную не составит большого труда. Но найти их все вручную не представляется возможным.

Я знаю об утилите «символические ссылки», и она полезна во многих сценариях, таких как поиск оборванных символических ссылок, но, похоже, у нее нет возможности обнаруживать «цепочки», подобные этой.

Я знаю о «find -type l», а также о параметре -L для поиска, но они, похоже, не работают вместе, поскольку «find -L -type l» всегда возвращает пустой ответ.

Я использую «find -type l -exec ls -l {} +» (который работает лучше, чем параметр find -ls) и пытался использовать его для получения списка пунктов назначения символических ссылок, которые я мог бы затем проверить, чтобы увидеть, символические ссылки или нет, однако все символические ссылки являются относительными, а не абсолютными, поэтому вывод немного запутан

например, я получаю такие результаты:

lrwxrwxrwx 1 имя пользователя 50 5 ноя 01:00 ./a/b/c/d -> ../../e/f/g/h

Из этого мне нужно немного подумать, чтобы понять, что фактическое место назначения символической ссылки — ./a/e/f/g/h (и затем я могу проверить, является ли это символической ссылкой или нет), не совсем идеально для автоматизации

Если бы символические ссылки были (временно) абсолютными, а не относительными, это было бы проще, но утилита «символические ссылки» может преобразовывать только абсолютные -> относительные; насколько я могу судить, он не может преобразовать относительный -> абсолютный.

Рейтинг:1
флаг nl

По всей цепочке ссылок

реальный путь

реальный путь (1) дает вам абсолютный пункт назначения ссылки. Но это только дает вам окончательный место назначения, поэтому, если у вас есть цепочка ссылок, она покажет вам только путь к последнему реальному файлу/папке, на который в конечном итоге указывает цепочка.

Итак, в вашем случае, если ../../e/f/g/h является реальным файлом или папкой, вы увидите абсолютный путь. Но если один из компонентов также является символической ссылкой, он будет рекурсивно сохраняться до тех пор, пока не разрешит все символические ссылки на пути.

ссылка для чтения

Вы также можете использовать ссылка для чтения(1) команда с флагами -f или -e, которая даст вам результат, аналогичный реальный путь.

  -f, --canonicalize канонизировать, переходя по каждой символической ссылке в
                                каждый компонент данного имени рекурсивно;
                                все, кроме последнего компонента, должны существовать
  -e, --canonicalize-существующие канонизировать, перейдя по каждой символической ссылке в
                                каждый компонент данного имени рекурсивно,
                                все компоненты должны существовать

Избегайте перехода по всей цепочке ссылок

Если я правильно понимаю, вы не хотите следовать по цепочке до последнего компонента, а хотите получить только абсолютный путь фактической ссылки. Это немного некрасиво, но вы можете сделать что-то вроде:

ССЫЛКА=./a/b/c/d
/usr/bin/realpath --no-symlinks "$(dirname ${LINK})/$(readlink ${LINK})"

Объяснение:

$ имя_каталога $LINK # имя_каталога ./a/b/c/d
./а/б/в

$ ссылка для чтения $LINK # ссылка для чтения ./a/b/c/d
../../e/f/g/h

$ echo "$(имя каталога ${LINK})/$(ссылка для чтения ${LINK})" 
./a/b/c/../../e/f/g/h

$ /usr/bin/realpath --no-symlinks "$(dirname ${LINK})/$(readlink ${LINK})"
/дом/а/д/ж/г/ч

Если вы хотите видеть только ссылку, относящуюся к вашему CWD, вы можете добавить аргумент --relative-to:

$ /usr/bin/realpath --no-symlinks --relative-to ./ "$(dirname ${LINK})/$(readlink ${LINK})"
а/д/ж/г/ч

Использование поиска

Вы можете получить аргумент для команды realpath, которую я показал ранее, используя команду find:

$ find ./ -type l -printf "%h/%l\n"
./a/b/c/../../e/f/g/h

От человека найти:

%h Начальные каталоги имени файла (все, кроме последнего элемента). Если
       имя файла не содержит косых черт (поскольку оно находится в текущем
       каталог) спецификатор %h заменяется на ".".

%l Объект символической ссылки (пустая строка, если файл не является символической ссылкой).

Затем вы можете комбинировать его с командой realpath сверху.

$ find ./ -type l -printf "%h/%l\n" | xargs /usr/bin/realpath -s
/дом/а/д/ж/г/ч

Если вы хотите видеть только ссылку, относящуюся к вашему CWD:

$ find ./ -type l -printf "%h/%l\n" | xargs /usr/bin/realpath -s --относительно ./
а/д/ж/г/ч
Displayname71 avatar
флаг ng
Интересно ... тот факт, что он следует по цепочке до конца, не идеален, но я мог бы сопоставить вывод реального пути с целевой информацией о «ls -l», чтобы увидеть, совпадают ли они
aviro avatar
флаг nl
Я отредактировал свой ответ и добавил еще один вариант, последний может быть тем, что вы ищете.
aviro avatar
флаг nl
@ Displayname71, я добавил в свой ответ еще несколько вариантов, надеюсь, один из них подойдет вам.

Ответить или комментировать

Большинство людей не понимают, что склонность к познанию нового открывает путь к обучению и улучшает межличностные связи. В исследованиях Элисон, например, хотя люди могли точно вспомнить, сколько вопросов было задано в их разговорах, они не чувствовали интуитивно связи между вопросами и симпатиями. В четырех исследованиях, в которых участники сами участвовали в разговорах или читали стенограммы чужих разговоров, люди, как правило, не осознавали, что задаваемый вопрос повлияет — или повлиял — на уровень дружбы между собеседниками.