Технічне пояснення
Причина того, що більшість методів викликає проблеми, полягає в тому, що 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 підпапок. (Забавно, як 100 М може розбитись до всього 100 і 4.)
Оскільки ми не перераховуємо файли, нам потрібно лише відслідковувати щонайменше 100 імен каталогів на рівні, максимум 4 × 100 = 400
каталогів у будь-який момент часу.
Тому потреба в пам'яті повинна становити ~ 206,25 КБ, що знаходиться в межах будь-якої сучасної (або іншої) системи.
Тест
На жаль (?) У мене немає системи з трильйонами файлів у мільйонах папок, тому я не в змозі перевірити це (я вважаю, що в останньому підрахунку, у мене було близько ~ 800 К файлів), тому хтось інший повинен буде спробувати це.
Caveat
Звичайно, пам'ять - не єдине обмеження. Диск теж буде великим вузьким місцем, тому що для кожного видаленого файлу та папки система повинна позначати його як безкоштовний. На щастя, багато з цих дискових операцій будуть поєднані разом (кешовані) та виписані фрагментами, а не окремо (принаймні для жорстких дисків, а не для знімних носіїв), але це все одно спричинить трохи збивання, як читає система і записує дані.