Есть ли более быстрый способ удалить директорию, чем “rm -rf”?

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

У меня есть папка, в которой много файлов, и команда “rm -rf” требует много времени для выполнения. Есть ли какой-то более быстрый способ удалить директорию и её содержимое (поддиректории и т.д.)?

Вы можете попробовать удалить inode для директории, но это оставит вам кучу осиротевших файлов, о которых fsck будет беспокоиться.

rm – это лучший вариант.


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

Если вы хотите удалить директорию и всё, что в ней, я предлагаю вам:

rm -rf путь/к/директории

rm внутри перечислит файлы и директории, которые собирается удалить. И это всё на скомпилированном C. Это две причины, почему он самый быстрый.

Это явно не то же самое, что rm -rf путь/к/директории/*, что расправляется на уровне оболочки и передает кучу аргументов в rm. Затем rm должен их разобрать и рекурсивно обработать каждый. Это намного медленнее.

Также как “бенчмарк”, который сравнивает find путь/к/директории -exec {} \;, является бессмысленным. Это выполняет rm один раз для каждого найденного файла. Очень медленно. Find может строить команды в стиле xargs с помощью -exec rm {} +, но это так же медленно, как распаковка. Вы можете вызвать -delete, который использует внутренний вызов unlink к ядру (как делает rm), но это будет работать только для файлов в первую очередь.

Так что, повторяю, если вы не бросите диск в жидкую горячую магму, rm – король.


На смежной ноте, разные файловые системы удаляют вещи с разной скоростью из-за их структуры. Если вы делаете это регулярно, вам может быть лучше хранить эти файлы на разделе, отформатированном в XFS, который обычно обрабатывает удаления довольно быстро.

Или используйте более быстрый диск. Если у вас много оперативной памяти, использование /dev/shm (диск на основе оперативной памяти) может быть хорошей идеей.

Если вам не нужно свободное место, самый быстрый способ – отложить удаление и сделать это в фоновом режиме:

  • mkdir .delete_me
  • mv большая-директория-которую-я-хочу-удалить .delete_me

Затем создайте crontab, который выполняет это в фоновом режиме, в спокойное время, с низким приоритетом ввода-вывода:

3 3 * * * root ionice -c 3 nice find /path/to/.delete_me -maxdepth 1 ! -name \. -exec echo rm -rf "{}" +

Заметки:

  • Проверьте свой вывод, прежде чем удалять команду echo в crontab!
  • Директория .delete_me должна находиться в одной файловой системе – на случай, если это не очевидно для всех.

Обновление:
Я нашёл интересный трюк, чтобы запускать несколько rm параллельно – это поможет, если у вас большой массив дисков:

ionice -c 3 nice find целевая_директория -depth -maxdepth 3 | xargs -d \n -P 5 -n 5 rm -rf
  • -depth для выполнения обхода в глубину.

  • -maxdepth, чтобы ограничить глубину обхода директорий, чтобы мы не вели учет отдельных файлов.

  • -d \n для обработки пробелов в именах файлов.

  • -P и -n обрабатывают степень параллелизма (проверьте man-страницу).

Источник: http://blog.liw.fi/posts/rm-is-too-slow/#comment-3e028c69183a348ee748d904a7474019

Обновление 2 (2018):
С ZFS, который поставляется с Ubuntu 18.04, я использую его для всего и создам новый набор данных для любого большого проекта. Если вы заранее планируете и делаете это заранее, вы можете просто “zfs destroy” файловую систему, когда закончите. 😉

Я использовал инструкции из вики zfsonlinux для установки Ubuntu на ZFS нативно:
https://github.com/zfsonlinux/zfs/wiki/Ubuntu-18.04-Root-on-ZFS

Иногда find $DIR_TO_DELETE -type f -delete быстрее, чем rm -rf.

Вы также можете попробовать mkdir /tmp/empty && rsync -r --delete /tmp/empty/ $DIR_TO_DELETE.

Наконец, если вам нужно удалить содержимое целого раздела, самым быстрым способом, вероятно, будет umount, mkfs и повторное mount.

Я думаю, что проблема в том, что нет идеального способа удалить очень большую директорию и весь её набор содержимого без настоящей индексированной файловой системы, которая понимает удаление и не предполагает, что у неё отсутствуют файлы, как в случае с FSCK. Должно быть какое-то доверие.

Например, у меня работает zoneminder для гольф-поля. Я создал RAID на Linux размером 1,5 ТБ, чтобы обрабатывать огромное количество данных, которые она захватывает за день (12 потоков с камер). Как она работала на 120 ГБ диске, не понятно. В общем, папка со всеми захваченными данными занимает около 1,4 ТБ её хранилища. Много чего нужно удалить.

Переустановка ZM и очистка старой библиотеки размером 1,4 ТБ – это не весело, потому что на удаление старых изображений может потребоваться 1 – 2 дня.

Настоящая индексированная файловая система позволяет удалить директорию и знает, что данные под ней мёртвы, и обнуление данных – это пустая трата нашего времени и ресурсов ПК. Это должно быть опционально – обнулять удалённые данные. RM просто занимает слишком много времени в реальном мире на ext4.

Ответ:
Рекурсивное удаление всех файлов было бы немного быстрее, но вам всё равно нужно будет выделить время для запуска FSCK.

Создайте скрипт, который выполняет рекурсивную команду “FOR”, чтобы “удалить” все файлы под вашими папками, а затем просто rm или rmdir все папки, чтобы очистить это. Вручную запустите FSCK, чтобы обнулить остальные данные, когда это будет удобно. Немного лениво, не записал это, извините :).

Хотя это не полезно, если вы хотите очистить существующую директорию, я упомяну, что возможной стратегией, если вы знаете, что у вас будет директория с множеством файлов, которые вам нужно регулярно очищать, это поместить директорию на собственную файловую систему (например, раздел). Затем, когда вам нужно очистить её, отмонтируйте её, выполните mkfs и перемонтируйте. Например, OpenBSD рекомендует делать это для /usr/obj, где создаётся много файлов во время сборки системы и их нужно удалить перед следующей сборкой.

Я создал многопоточную замену для rm с единственной целью быть самым быстрым способом удаления файлов, точка. В моем тестировании худший результат составляет 20% быстрее всего остального и, как правило, в 2-3 раза быстрее, чем rm.

Инструмент: https://github.com/SUPERCILEX/fuc/tree/master/rmz
Бенчмарки: https://github.com/SUPERCILEX/fuc/tree/master/comparisons#remove

Самый быстрый способ рекурсивно удалить все файлы и папки, который я смог придумать: (это быстрее, чем всё, что здесь опубликовано, так что определённо быстрее, чем rm -rf):

perl -le 'use File::Find; find(sub{unlink if -f}, ".")' && rm -rf *

Больше деталей и бенчмарков можно найти здесь: https://www.slashroot.in/which-is-the-fastest-method-to-delete-files-in-linux

Это результаты тестирования:

Команда Find с -exec: 14 минут для полумиллиона файлов
Команда Find с -delete: 5 минут для полумиллиона файлов
Perl: 1 минута для полумиллиона файлов
RSYNC с -delete: 2 минуты 56 секунд для полумиллиона файлов

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

Быстрые способы удаления директории и её содержимого без использования команды rm -rf

Удаление больших директорий и их содержимого может потребовать значительных временных ресурсов, особенно если в них содержится множество файлов. Одна из самых распространённых команд для этой задачи — rm -rf, однако существуют альтернативные методы, которые могут оказаться более эффективными в определенных случаях. Рассмотрим различные подходы к удалению директорий и их содержимого, а также факторы, влияющие на скорость выполнения.

1. Внутренние особенности rm

Команда rm -rf оптимизирована на уровне C и внутренняя структура этой утилиты позволяет ей эффективно справляться с задачей рекурсивного удаления. Однако, если вы сталкиваетесь с длительным временем выполнения, скорее всего это связано с рядом факторов, таких как количество файлов, нагрузка на диск, файловая система и аппаратные характеристики.

  • Удаление с помощью find:
    Вы можете рассмотреть использование команды find с опцией -delete. Например, команда:

    find path/to/directory -type f -delete

    Может быть быстрее, чем rm -rf в определённых сценариях, особенно если количество файлов значительно.

  • Удаление с unlink:
    Если вам не нужно освобождать место немедленно, вы можете переместить директорию для удаления в отдельный каталог, а затем задать задание в cron для удаления запланированным образом, используя unlink или find:

    mkdir .delete_me
    mv path/to/directory .delete_me

    Затем добавьте cron-задание, например:

    3 3 * * * root ionice -c 3 nice find /path/to/.delete_me -maxdepth 1 ! -name \. -exec echo rm -rf "{}" +

3. Параллельное удаление

Если у вас есть система с большим количеством дисков или файлов, вы можете использовать параллельное удаление. Например:

ionice -c 3 nice find target_directory -depth -maxdepth 3 | xargs -d \n -P 5 -n 5 rm -rf

Эта команда позволит запустить до 5 параллельных процессов rm, что может значительно ускорить выполнение операции удаления.

4. Использование специализированных инструментов

Некоторые пользователи разработали собственные инструменты для более быстрого удаления файлов. Например, проект на GitHub rmz демонстрирует улучшенную производительность по сравнению с rm. Бенчмаркинг может показать, что этот инструмент удаляет файлы на 20% быстрее.

5. Умаршивание и создание файловой системы

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

6. Использование в оперативной памяти

Если у вас много оперативной памяти, можно использовать временную директорию, смонтированную как RAM-диск, например, /dev/shm. Это позволит значительно ускорить операции записи и удаления.

Заключение

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

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

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