
Есть ли способ найти все символические ссылки, которые никуда не указывают?
find ./ -type l
выдаст мне все символические ссылки, но не делает различий между ссылками, ведущими куда-то, и ссылками, ведущими куда-то нет.
В настоящее время я занимаюсь:
find ./ -type l -exec file {} \; | grep broken
Но мне интересно, какие существуют альтернативные решения.
решение1
Я бы настоятельно рекомендовалнетиспользовать find -L
для задачи (см. ниже объяснение). Вот несколько других способов сделать это:
Если вы хотите использовать «чистый
find
» метод и предполагаете реализацию GNUfind
, то это должно выглядеть примерно так:find . -xtype l
(
xtype
тест, выполняемый на разыменованной ссылке)переносимо (хотя и менее эффективно) вы также можете выполнить
test -e
командуfind
:find . -type l ! -exec test -e {} \; -print
Даже какой-то
grep
трюк мог бы быть лучше (т.е.безопаснее), чемfind -L
, но не совсем такой, как представлено в вопросе (который выполняет grep во всех выходных строках, включая имена файлов):find . -type l -exec sh -c 'file -b "$1" | grep -q "^broken"' sh {} \; -print
Трюк find -L
цитируетсясолооткомандная строкаfuвыглядит красиво и некрасиво, но у него есть одна оченьопасная ловушка: Все символические ссылки пройдены. Рассмотрим каталог с содержимым, представленным ниже:
$ ls -l
total 0
lrwxrwxrwx 1 michal users 6 May 15 08:12 link_1 -> nonexistent1
lrwxrwxrwx 1 michal users 6 May 15 08:13 link_2 -> nonexistent2
lrwxrwxrwx 1 michal users 6 May 15 08:13 link_3 -> nonexistent3
lrwxrwxrwx 1 michal users 6 May 15 08:13 link_4 -> nonexistent4
lrwxrwxrwx 1 michal users 11 May 15 08:20 link_out -> /usr/share/
Если вы запустите find -L . -type l
в этом каталоге, все /usr/share/
также будет прочитано (и это может занять очень много времени) 1 .Для find
команды, которая «невосприимчива к исходящим ссылкам», не используйте-L
.
1 Это может показаться незначительным неудобством (команда «просто» долго будет обходить все /usr/share
) – но может иметь более серьезные последствия. Например, рассмотрим среды chroot: они могут существовать в каком-то подкаталоге основной файловой системы и содержать символические ссылки на абсолютные местоположения. Эти ссылки могут показаться неработоспособными для «внешней» системы, поскольку они указывают на нужные места только после того, как вы вошли в chroot. Я также припоминаю, что некоторые загрузчики использовали символические ссылки, которые /boot
имели смысл только на начальной стадии загрузки, когда загрузочный раздел был смонтирован как /
.
Так что если вы используете find -L
команду для поиска и удаления неработающих символических ссылок из какого-то безобидного на вид каталога, вы можете даже сломать свою систему...
решение2
Как уже прокомментировал rozcietrzewiacz, find -L
может иметь неожиданные последствия расширения поиска в симлинкованные каталоги, поэтому это не оптимальный подход. О чем еще никто не упомянул, так это о том, что
find /path/to/search -xtype l
является более краткой и логически идентичной командой
find /path/to/search -type l -xtype l
Ни одно из представленных на данный момент решений не позволяет обнаружить циклические символические ссылки, что является еще одним типом поломки. этот вопросрешает проблему переносимости. Подводя итог, переносимый способ поиска сломанных символических ссылок, включая циклические ссылки, это:
find /path/to/search -type l -exec test ! -e {} \; -print
Более подробную информацию см.этот вопросилиynform.org. Конечно, окончательным источником всего этого являетсядокументация findutils.
решение3
Команда symlinks
отhttp://www.ibiblio.org/pub/Linux/utils/file/symlinks-1.4.tar.gzможет использоваться для идентификации символических ссылок с различными характеристиками. Например:
$ rm a
$ ln -s a b
$ symlinks .
dangling: /tmp/b -> a
решение4
Я считаю, что добавление -L
флага к вашей команде позволит вам избавиться от grep
:
$ find -L . -type l
http://www.commandlinefu.com/commands/view/8260/find-broken-symlinks
из руководства:
-L
Заставить возвращаемую для каждой символической ссылки информацию о файле и тип файла (см.
stat
(2)) быть данными файла, на который ссылается ссылка, а не самой ссылки. Если файл, на который ссылается ссылка, не существует, информация о файле и тип будут для самой ссылки.