Техническое объяснение
Причина, по которой большинство методов вызывают проблемы, заключается в том, что Windows пытается перечислить файлы и папки. Это не большая проблема с несколькими сотнями или даже тысячами файлов / папок глубиной в несколько уровней, но если у вас есть триллионы файлов в миллионах папок, идущие на десятки уровней глубины, то это определенно приведет к падению системы ,
Предположим, у вас есть «только» 100 000 000 файлов, и Windows использует простую структуру, подобную этой, для хранения каждого файла вместе с его путем (таким образом вы избегаете хранения каждого каталога по отдельности, тем самым сохраняя некоторые издержки):
struct FILELIST { // Total size is 264 to 528 bytes:
TCHAR name[MAX_PATH]; // MAX_PATH=260; TCHAR=1 or 2 bytes
FILELIST* nextfile; // Pointers are 4 bytes for 32-bit and 8 for 64-bit
}
В зависимости от того, использует ли он 8-разрядные символы или символы Unicode (он использует Unicode) и является ли ваша система 32-разрядной или 64-разрядной, для хранения списка потребуется от 25 до 49 ГБ памяти (и это очень упрощенная структура).
Причина, по которой Windows пытается перечислить файлы и папки перед их удалением, варьируется в зависимости от метода, который вы используете для их удаления, но это делают как Проводник, так и интерпретатор команд (вы можете увидеть задержку при запуске команды). Вы также можете увидеть, как мигает индикатор активности диска (HDD), когда он читает дерево каталогов с диска.
Решение
Лучше всего справляться с подобной ситуацией, используя инструмент удаления, который удаляет файлы и папки по отдельности, по одному за раз. Я не знаю, есть ли какие-либо готовые инструменты для этого, но это должно быть возможно сделать с помощью простого пакетного файла.
@echo off
if not [%1]==[] cd /d %1
del /q *
for /d %%i in (*) do call %0 "%%i"
Для этого нужно проверить, был ли передан аргумент. Если это так, то он изменяется на указанный каталог (вы можете запустить его без аргумента, чтобы запустить в текущем каталоге или указать каталог - даже на другом диске, чтобы он начинался там).
Далее он удаляет все файлы в текущем каталоге. В этом режиме он не должен ничего перечислять и просто удалять файлы, не занимая много, если таковые имеются, памяти.
Затем он перечисляет папки в текущем каталоге и вызывает себя, передавая каждую папку ему (себе) для рекурсии вниз.
Анализ
Причина, по которой это должно работать, состоит в том, что он не перечисляет каждый отдельный файл и папку во всем дереве . Он не перечисляет файлы вообще, а только перечисляет папки в текущем каталоге (плюс остальные в родительских каталогах). Предполагая, что в любой данной папке есть только несколько сотен подкаталогов, тогда это не должно быть слишком плохо, и, конечно, требует намного меньше памяти, чем другие методы, которые перечисляют все дерево.
Вы можете задаться вопросом об использовании /r
ключа вместо (ручной) рекурсии. Это не сработает, потому что, хотя /r
коммутатор выполняет рекурсию, он предварительно перечисляет все дерево каталогов, чего мы и хотим избежать; мы хотим удалить, как мы идем, не отслеживая.
сравнение
Давайте сравним этот метод с методом полного перечисления.
Вы сказали, что у вас есть «миллионы каталогов»; скажем 100 миллионов. Если дерево приблизительно сбалансировано и предполагается, что в среднем около 100 подкаталогов на папку, то самый глубокий вложенный каталог будет примерно на четыре уровня ниже - на самом деле в целом дереве будет 101 010 100 подпапок. (Забавно, как 100M может сломаться до 100 и 4.)
Поскольку мы не перечисляем файлы, нам нужно отслеживать не более 100 имен каталогов на уровень, для максимального количества 4 × 100 = 400
каталогов в любой момент времени.
Следовательно, требования к памяти должны составлять ~ 206,25 КБ, что находится в пределах любой современной (или иной) системы.
Тестовое задание
К сожалению (?) У меня нет системы с триллионами файлов в миллионах папок, поэтому я не могу ее протестировать (я считаю, по последним подсчетам, у меня было около ~ 800 КБ файлов), поэтому кому-то еще придется попробовать Это.
Предостережение
Конечно, память - не единственное ограничение. Диск также будет большим узким местом, потому что для каждого файла и папки, которую вы удаляете, система должна пометить его как свободный. К счастью, многие из этих дисковых операций будут объединены вместе (кэшированы) и записаны в виде кусков, а не по отдельности (по крайней мере, для жестких дисков, а не для съемных носителей), но это все равно будет вызывать небольшие колебания, когда система читает и пишет данные.