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

Вопрос или проблема

Я создал символьные ссылки на большое количество файлов журналов. Синтаксис файлов журналов — yyyymmdd.log.gz.

Чтобы упростить задачу, я использую простую последовательность без парсинга с помощью date:

for dd in $(seq -w 20150101 20151231) ; do 
     ln -s $origin/$dd.log.gz $target/$dd.log.gz
done

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

Эта простая однострочная команда выполняет задачу довольно быстро. Она требует GNU Findutils:

find . -xtype l -delete

Немного объяснений:

-xtype l проверяет на наличие сломанных ссылок (это противоположность -type)

-delete удаляет файлы непосредственно, без необходимости дальнейшего использования xargs или -exec

ПРИМЕЧАНИЕ: -xtype l означает -xtype строчная L (как в link) 😉

find -L /path -type l -exec rm -i {} \;

С помощью -L команда find пытается следовать по символьным ссылкам, чтобы оценить тест -type. Если она может следовать по ссылке, значит, ссылка не сломана, и тест -type l будет ложным (так как он оценивается по объекту, на который ссылается ссылка). Если она не может следовать по ссылке, то ссылка сломана, и тест -type l будет истинным.

Если тест -type l проходит успешно, тогда команда -exec rm {} \; удаляет сломанную ссылку.

Предложение использовать -xtype l является GNU-признаком, в первую очередь для пользователей Linux, и не будет работать на ненадежных UNIX-системах, таких как Solaris, FreeBSD и т. д.

С помощью zsh (вы на самом деле используете синтаксис zsh в своем коде; в bash вам нужно будет заключить переменные в кавычки):

rm -- $target/*(-@)

Или:

rm -- $target/<20150101-20151231>.log.gz(-@)

*(@) соответствует файлам типа символьная ссылка. *(-@) — это те, которые все еще являются типом символьная ссылка после разрешения символьной ссылки (то есть те, для которых цель символьной ссылки не может быть разрешена). Это эквивалентно -xtype l в GNU find.

В zsh и с GNU ln вы бы написали свой цикл так:

ln -srt $target -- $origin/<20150101-20151231>.log.gz

Что также сработает, даже если $origin содержит относительный путь (и создает относительные символьные ссылки, что снижает риск поломки символьных ссылок, если некоторые компоненты пути origin (те, которые общие с target) будут переименованы в будущем).

Ответ Роба Каррента определенно полезен и работает.

Еще один пример можно найти через man find на macOS для удаления всех сломанных символьных ссылок в заданном каталоге.

Допустим, у вас есть каталог /usr/ports/packages, содержащий сломанные символьные ссылки на другие файлы или каталоги, которые были перемещены или удалены, следующая команда удалит все символьные ссылки, для которых ранее связанный файл больше не существует.

EXAMPLES
    Следующие примеры представлены так, как они даны оболочке:
    ...

    find -L /usr/ports/packages -type l -exec rm -- {} +
           Удаляет все сломанные символьные ссылки в /usr/ports/packages.
     ...
BSD                           28 сентября 2011                           BSD

Опция -L (в соответствии с man find) заставляет информацию о файле и тип файла, возвращаемые для каждой символьной ссылки, быть таковыми, как для файла, на который ссылается ссылка, а не самой ссылки. Если же упомянутый файл не существует, информация о файле и тип будут для самой ссылки.

Опция -type l ограничивает найденные файлы только теми, которые являются символьными ссылками.

Что следует после оператора -exec, это команда для выполнения для соответствующих файлов.

Оператор -- заставляет rm, который использует getopt(3) для разбора своих аргументов, прекратить обработку опций флагов после этого.

Как объясняет man find, синтаксис exec utility [argument ...] {} + имеет тот же эффект, что и -exec, за исключением того, что “{}” заменяется на максимальное количество имен файлов для каждого вызова утилиты. Это поведение похоже на поведение команды xargs(1).

Надеюсь, это поможет.

Если все сломанные ссылки были созданы из-за ошибки команды в определенный момент времени, то следующий вариант сработает хорошо.

ls -lrt | grep "Sep 17 15:06" | awk '{print $9}' | xargs \rm

Учитывая детали вопроса, возможно, вам стоит использовать:

find . -maxdepth 1 -xtype l -delete 

Ответ или решение

Удаление сломанных символических ссылок в системах UNIX/Linux может быть выполнено несколькими способами. Ниже я описываю наиболее эффективные методы, которые позволят вам быстро и просто избавиться от этих ссылок.

Метод 1: Использование команды find

Команда find — это мощный инструмент, который позволяет находить и удалять файлы в иерархии каталогов. Чтобы удалить все сломанные символические ссылки, вы можете использовать следующую команду:

find . -xtype l -delete

Объяснение компонентов команды:

  • find — команда для поиска файлов и каталогов.
  • . — указывает на текущий каталог; вы можете заменить его на путь к интересующему каталогу.
  • -xtype l — находит только сломанные символические ссылки.
  • -delete — удаляет найденные файлы без необходимости дополнительных действий.

Метод 2: Альтернативный метод для macOS и FreeBSD

Если вы используете macOS или другую систему, которая не поддерживает -xtype, можете воспользоваться следующим подходом:

find -L /path/to/directory -type l -exec rm -- {} +

Краткая информация о ключевых параметрах:

  • -L — заставляет find следовать символическим ссылкам. Если целевой файл недоступен, -type l будет истинным для сломанной ссылки.
  • -type l — ограничивает поиск только символическими ссылками.
  • -exec rm -- {} + — выполняет команду удаления для всех найденных символических ссылок.

Метод 3: Команда rm в оболочке zsh

Если вы используете оболочку zsh, вы можете использовать следующий синтаксис:

rm -- $target/*(-@)

Здесь *($@) находит все символьные ссылки, а *(-@) — только те, которые не имеют действительного целевого файла.

Примечания

  1. Системные ограничения: Обратите внимание, что подходы, зависящие от использования -xtype, в основном ограничены системами на основе GNU. На других системах, таких как Solaris и FreeBSD, имеет смысл использовать -L с -type l.

  2. Безопасность удаления: Если вы хотите убедиться, что удаление выполняется корректно, добавьте ключ -i к команде rm, чтобы запрашивать подтверждение перед удалением каждой ссылки:

find . -xtype l -exec rm -i {} \;
  1. Ограничение глубины поиска: Если вы хотите удалить сломанные ссылки только в текущем каталоге, используйте -maxdepth 1:
find . -maxdepth 1 -xtype l -delete

Заключение

Использование команды find со специальными опциями является самым эффективным способом удаления сломанных символических ссылок в Unix-подобных системах. Этот метод не только быстр, но и позволяет избегать случайных ошибок при удалении. Важно помнить о типе системы, чтобы выбрать правильный командный синтаксис.

Следуя предложенным методам и рекомендациям, вы сможете эффективно управлять своими символическими ссылками и поддерживать порядок в файловой системе.

Оцените материал
Добавить комментарий

Капча загружается...