Как удалить все файлы в папке

Обновлено: 03.07.2024

Ничто не предвещало беды.
Сервер с сайтом работал без никаких проблем уже больше года (uptime почти 500 дней), не было никаких проблем, и я с чистой душой спокойно ушел в отпуск.

В первый же день отпуска мне звонят с жалобой — сайт недоступен. MySQL падает с ошибкой Error 28 «No space left on device».

Казалось бы, проблема банальна — кончилось место на диске. Правда, df -h показывает, что на диске имеется вполне достаточное количество свободного места, ну да я же в отпуске, разбираться лень — посоветовал им поискать на диске ненужные файлы (старые бекапы и т.д.) и их удалить. Удалили, вроде все заработало.

Прошла пара часов и проблема вернулась. Странно — свободное место на жестком диске за это время практически не уменьшилось. После беглого гугления обнаружился топик на serverfault, в котором говорится, что проблема может возникнуть также из-за того, что кончилось не место на диске, а айноды!

Ввожу в консоль df -i — и оказывается действительно, айноды у меня закончились.

Проблема

Начал искать, где же у меня находится столько файлов на жестком диске, что они сожрали все айноды (а айнодов у меня на 500-гигабайтном жестком диске больше 30 миллионов).

И нашел — оказалось, проблема была в папке с сессиями php.

Видимо, по какой-то причине сломался механизм автоочистки этой папки, что привело к тому, что в ней скопилось огромное количество файлов. Насколько огромное — сказать сложно, потому что никакие стандартные команды линукс, такие, как ls, find, rm и т.д. — с этой папкой не работают. Просто виснут, заодно подвешивая весь сервер. Могу только сказать, что сам файл директории стал весит около гигабайта, а также что файлов там точно более полумиллиона, потому что столько я оттуда уже удалил.

Решение

Решение очевидное — надо удалить все эти файлы сессий. При этом желательно, чтобы сервер продолжал работать в штатном режиме. Для начала я переименовал папку сессий, в которой лежит куча файлов, а вместо нее создал пустую — чтобы спокойно из старой (переименованной) удалять все файлы, и чтобы это не мешало созданию новых файлов сессий.

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

И перешел к основной проблеме — очистке жесткого диска.

Попробовал решение «в лоб»:

Сервер повис, ничего не удалилось

Попробовал известный способ для удаления большого числа файлов


Ничего, сервер виснет, файлы не удаляются.

А теперь что самое интересное — файловый менеджер mc достаточно успешно справлялся с задачей удаления этих файлов! То есть, когда запускаешь удаление папки — файлы удаляются, mc не виснет. Удаление идет со скоростью примерно 5 000 файлов в минуту, правда при этом создается огромная нагрузка на жесткий диск, что приводит к неработоспособности сервера.

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

Собственно, решение опять нашлось в гугле — Olark делится способом, как он отобразил список из 8 миллионов файлов в 1 папке, используя системный вызов getdents

Здесь находится документация по функции getdents, а также пример кода, который ее использует.

Правда, этот пример мне не совсем подошел — даже если ставить большой размер буфера, как советует Olark в своем блоге, все равно сервер виснет при попытке прочитать всю папку разом.

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

В итоге у меня получился такой код:


Код компиллируется обычным gcc


И просто запускается из командной строки:


Получившийся файл я поставил в крон и теперь у меня удаляется по 547 файлов в минуту, при этом нагрузка на сервер в пределах нормы — и я надеюсь, в течение недели-другой все файлы все-таки удалятся.



Феерическая расстановка точек над i в вопросе удаления файлов из переполненной директории.

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

Для тех, кто не в курсе проблемы, краткое описание: если вы случайно создали в одной директории огромное количество файлов без иерархии — т.е. от 5 млн файлов, лежащих в одной единственной плоской директории, то быстро удалить их не получится. Кроме того, не все утилиты в linux могут это сделать в принципе — либо будут сильно нагружать процессор/HDD, либо займут очень много памяти.

Так что я выделил время, организовал тестовый полигон и попробовал различные средства, как предложенные в комментариях, так и найденные в различных статьях и свои собственные.

Подготовка

Так как создавать переполненную директорию на своём HDD рабочего компьютера, потом мучиться с её удалением ну никак не хочется, создадим виртуальную ФС в отдельном файле и примонтируем её через loop-устройство. К счастью, в Linux с этим всё просто.

Создаём пустой файл размером 200Гб

Многие советуют использовать для этого утилиту dd, например dd if=/dev/zero of=disk-image bs=1M count=1M , но это работает несравнимо медленнее, а результат, как я понимаю, одинаковый.

Форматируем файл в ext4 и монтируем его как файловую систему

К сожалению, я узнал об опции -N команды mkfs.ext4 уже после экспериментов. Она позволяет увеличить лимит на количество inode на FS, не увеличивая размер файла образа. Но, с другой стороны, стандартные настройки — ближе к реальным условиям.

Создаем множество пустых файлов (будет работать несколько часов)

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

Проверяем, что все айноды на ФС исчерпаны.

Размер файла директории

Теперь попробуем удалить эту директорию со всем её содержимым различными способами.

Тесты

После каждого теста сбрасываем кеш файловой системы
sudo sh -c 'sync && echo 1 > /proc/sys/vm/drop_caches'
для того чтобы не занять быстро всю память и сравнивать скорость удаления в одинаковых условиях.

Удаление через rm -r

$ rm -r /mnt/test_dir/
Под strace несколько раз подряд (. ) вызывает getdents() , затем очень много вызывает unlinkat() и так в цикле. Занял 30Мб RAM, не растет.
Удаляет содержимое успешно.

Т.е. удалять переполненные директории с помощью rm -r /путь/до/директории вполне нормально.

Удаление через rm ./*

$ rm /mnt/test_dir/*
Запускает дочерний процесс шелла, который дорос до 600Мб, прибил по ^C . Ничего не удалил.
Очевидно, что glob по звёздочке обрабатывается самим шеллом, накапливается в памяти и передается команде rm после того как считается директория целиком.

Удаление через find -exec

$ find /mnt/test_dir/ -type f -exec rm -v <> \;
Под strace вызывает только getdents() . процесс find вырос до 600Мб, прибил по ^C . Ничего не удалил.
find действует так же, как и * в шелле — сперва строит полный список в памяти.

Удаление через find -delete

$ find /mnt/test_dir/ -type f -delete
Вырос до 600Мб, прибил по ^C . Ничего не удалил.
Аналогично предыдущей команде. И это крайне удивительно! На эту команду я возлагал надежду изначально.

Удаление через ls -f и xargs

$ cd /mnt/test_dir/ ; ls -f . | xargs -n 100 rm
параметр -f говорит, что не нужно сортировать список файлов.
Создает такую иерархию процессов:

Удаление через perl readdir

$ perl -e 'chdir "/mnt/test_dir/" or die; opendir D, "."; while ($n = readdir D) < unlink $n >' (взял здесь)
Под strace один раз вызывает getdents() , потом много раз unlink() и так в цикле. Занял 380Кб памяти, не растет.
Удаляет успешно.

Получается, что использование readdir вполне возможно?

Удаление через программу на C readdir + unlink

$ gcc -o cleandir cleandir.c
$ ./cleandir
Под strace один раз вызывает getdents() , потом много раз unlink() и так в цикле. Занял 128Кб памяти, не растет.
Удаляет успешно.

Опять — же, убеждаемся, что использовать readdir — вполне нормально, если не накапливать результаты в памяти, а удалять файлы сразу.

У меня большое количество посетителей в день и создаётся до 50 тысяч сессий в день. Пишу скрипт, чтобы когда число сессий в папке mod-tmp превысит 20 тысяч, сервер удалял бы из неё все файлы и перезагружался. Помогите, пожалуйста, как с помощью PHP удалить все файлы из 1 папки?


8,768 10 10 золотых знаков 26 26 серебряных знаков 54 54 бронзовых знака 161 1 1 золотой знак 2 2 серебряных знака 17 17 бронзовых знаков Вроде как нельзя удалить сразу все. Можно получить список и удалить в цикле, но это долго. Можно попробовать через exec запускать внешнюю программу. Или вообще написать демона который будет работать выше чем пхп и быстрее Довольно интересный я бы сказал не вопрос а ситуация. Копайте в торону cron php > чтобы когда число сессий в папке mod-tmp привышало 20 тысяч сервер удалял из неё все файлы и перезагружался Простите, но это форменный кошмар, других слов я просто не нахожу. Во-первых, PHP сам чистит протухшие сессии, если не менялись настройки session.gc-* А во-вторых, вас не волнует, что пользователей будет постоянно выкидывать с сайта, не говоря уже о неработоспособности сайта во время перезагрузки?

Вот самый быстрый и лёгкий способ:

Дальше вызываете где и когда нужно. К примеру, если это Wordpress, вешаете add_action('save_post','clear') .


6,920 5 5 золотых знаков 24 24 серебряных знака 64 64 бронзовых знака

Удалить средствами php сразу все не получится. Только в цикле. Возможно следует посмотреть в сторону демонов, как сказал @Inart.
Код для пхп:


6,920 5 5 золотых знаков 24 24 серебряных знака 64 64 бронзовых знака 3,766 16 16 серебряных знаков 24 24 бронзовых знака

Грубый подход, очень грубый:

Это сработает только в Linux. Еще раз скажу, подход очень грубый и лучше такого не использовать НИКОГДА.


6,920 5 5 золотых знаков 24 24 серебряных знака 64 64 бронзовых знака 1,208 1 1 золотой знак 9 9 серебряных знаков 23 23 бронзовых знака

Вероятно, всё намного проще. ISPManager криво меняет конфиг php отключая сборщик мусора сессий.

Открывайте конфиг php. По-дефолту /etc/php.d/apache/php.ini

Меняйте параметр session.gc_probability=0 в значение 1

Перезапускаете аппач /etc/init.d/apache2 restart

Всё, сборка мусора снова — дело php.



А попробуйте лучше удалять не все сразу, а постепенно. То есть PHP-скрипт каждого пользователя, который зашел к вам на сайт, будет удалять, например, по 1000 файлов, пока их не останется вовсе. Это сделать не сложно. Достаточно одного XML-Файла ( БД здесь не обязательно использовать) с двумя записями - сколько осталось и вторая - надо ли производить удаление.

Удалить изображение файла

Пользователи Microsoft Windows могут удалить файл или папку (каталог) разными способами. Ниже приведены наиболее распространенные способы удаления файла или папки.

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

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

Удалить файл или папку

Найдите элемент, который вы хотите удалить, выделите его, нажав один раз на файл или папку, и нажмите клавишу удаления на клавиатуре. Вы можете найти местоположение файла или папки, используя Мой компьютер или Проводник Windows.

Вы можете удалить несколько файлов или папок, удерживая клавишу Ctrl и щелкая каждый из них перед нажатием «Удалить».

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

Щелкните правой кнопкой мыши, чтобы удалить файл в Windows

Удалить файл или папку, щелкнув правой кнопкой мыши

Откройте Мой компьютер или Проводник Windows. Найдите файл или папку, которую вы хотите удалить, и щелкните по ней правой кнопкой мыши. Выберите опцию удаления из всплывающего меню.

Удалить из меню файла

Откройте Мой компьютер или Проводник Windows, найдите и выберите файл или папку, которую вы хотите удалить, нажмите файл в верхней строке меню и выберите удалять,

Если файл меню не отображается в «Моем компьютере» или в проводнике Windows, нажмите клавишу «Alt», чтобы отобразить строку меню, включая меню «Файл».

Проблемы при удалении

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

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

Другой возможной причиной проблем с удалением файла или папки является вирус или заражение вредоносным ПО. Вирусы и вредоносные программы могут препятствовать изменению или удалению файлов или папок. Если это так, вам нужно удалить вирус или вредоносное ПО, чтобы иметь возможность удалить затронутый файл или папку.

Как восстановить удаленный файл или папку

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

Как удалить файлы в MS-DOS и командной строке Windows

Помните, что любой удаленный файл или каталог в MS-DOS не отправляется в корзину Windows.

Прежде чем можно будет выполнить любой из следующих шагов, вы должны получить приглашение MS-DOS или командную строку Windows.

Файлы

Пользователи MS-DOS могут удалять файлы с помощью команды del. Ниже приведен пример использования этой команды.

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

Del: Команда может быть использована для удаления любого файла.

Удалить несколько файлов

Вы также можете использовать подстановочные знаки, если хотите удалить несколько файлов, как показано в примере ниже.

В приведенном выше примере эта команда удалит все файлы с расширением .txt.

Del: Команда может быть использована для удаления любого расширения файла.

Каталог

Пользователи MS-DOS могут удалять каталоги в MS-DOS с помощью команды deltree или rmdir. Смотрите любую из этих ссылок для получения дополнительной информации об этих командах. Ниже приведен пример того, как это можно использовать.

Удаление подкаталога

Если вы хотите удалить каталог внутри другого каталога (подкаталога), вы можете использовать команду, аналогичную приведенной ниже.

В приведенном выше примере каталог «test» в каталоге «example» будет удален. Вы также можете использовать команду cd, чтобы изменить каталог на каталог с примером, а затем удалить каталог «test», используя наш первый пример, показанный выше.

Как удалить каталог или имя файла с пробелом

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

В приведенных выше примерах мы удаляем файл с именем «my example file.txt» с кавычками, окружающими полное имя и расширение файла, и удаляем каталог «my example directory».

RmDir Команда может быть использована для удаления любого файла.

Как удалить файлы в Linux, Unix и других вариантах

Файлы

Пользователи Linux и Unix могут удалять файлы через консоль с помощью команды rm. Смотрите эту страницу для получения дополнительной информации об этой команде. Ниже приведен пример использования этой команды.

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

rm: Команда может быть использована для удаления любого файла.

Удалить несколько файлов

Вы также можете использовать подстановочные знаки, если хотите удалить несколько файлов, как показано в примере ниже.

В приведенном выше примере эта команда удалит все файлы с расширением .txt.

rm: Команда может быть использована для удаления любого файла с расширениями файлов.

Каталог

Пользователи Linux и Unix могут удалять папки через консоль с помощью команды rmdir. Смотрите эту страницу для получения дополнительной информации об этой команде. Ниже приведен пример использования этой команды.

Как и в Microsoft Windows, в Linux и Unix вы также можете удалять файлы через графический интерфейс, находя файл и нажимая клавишу удаления на клавиатуре.

Удаление подкаталога

Если вы хотите удалить каталог внутри другого каталога (подкаталога), вы можете использовать команду, аналогичную приведенной ниже.

В приведенном выше примере каталог «test» в каталоге «example» будет удален. Вы также можете использовать команду cd, чтобы изменить каталог на каталог с примером, а затем удалить каталог «test», используя наш первый пример, показанный выше.

Как удалить каталог или имя файла с пробелом

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

В приведенных выше примерах мы удаляем файл с именем «my example file.txt» с кавычками, окружающими полное имя и расширение файла, и удаляем каталог «my example directory».

RmDir Команда может быть использована для удаления любого файла.

Как удалить файлы в macOS

Пользователи Apple macOS могут удалить файл или папку (каталог) разными способами. Ниже приведены наиболее распространенные способы удаления файла или папки.

Пользователи, не знакомые с Apple macOS, должны понимать, что если вы удаляете папку, она удаляет все файлы и папки в этой папке.

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

Удалить элемент

Клавиша удаления на клавиатуре сама по себе не удаляет файл или папку в macOS. Чтобы удалить файл или папку, удерживайте нажатой клавишу «Command» и одновременно нажмите клавишу «Delete». Вы можете просмотреть местоположение файла или папки с помощью Finder.

Щелкните правой кнопкой мыши и выберите «Переместить в корзину».

Откройте Finder и найдите файл или папку, которую хотите удалить, и щелкните правой кнопкой мыши файл. В появившемся меню правой кнопкой мыши щелкните Переместить в корзину вариант.

Удалить из меню файла

Откройте Finder, найдите и выберите файл или папку, которую вы хотите удалить, нажмите файл в верхней строке меню и выберите Переместить в корзину,

Терминал

Чтобы удалить файлы или каталоги в командной строке терминала, используйте команду rm.

Как удалить файлы в Microsoft Windows 3.X

Файловый менеджер

  1. Открыть файловый менеджер
  2. Найдите папку или файл, который вы хотите удалить, затем нажмите файл и удалять,

MS-DOS

См. Выше раздел пользователя MS-DOS для получения информации об удалении каталога в MS-DOS.

Читайте также: