Как удалить огромное количество файлов в Windows

У меня есть каталог, содержащий миллионы подкаталогов и триллионов файлов. И теперь я должен это очистить. Говоря триллион, я не говорю о размере файла, а о количестве файлов.

Я попытался удалить его с помощью del/s и использовать проводник Windows. Ни одна из них не может выполнить задачу. Я попытался удалить некоторые из подкаталогов один за другим, и это заняло у меня много дней. Проблема, с которой я столкнулся, заключалась в том, что каждый раз, независимо от использования del или Explorer, я могу видеть в диспетчере задач, что экземпляр explorer потребляет небывалую память и постепенно подталкивает мою систему к сбою.

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


[EDITED]

Я попытался сделать это с Cygwin rm -fr и дал тот же результат. Обобщены как:

  1. Независимо от того, используется ли проводник Windows, DEL из командной строки или команда Cygwin rm , системная память постепенно падает до нуля, и окно в конечном итоге сбой.

  2. Если в какой-либо момент, перед сбоем системы, процесс закрывается (CTRL + C или что еще), поле будет продолжать работать как обычно. Однако вся используемая память НЕ будет освобождена. Скажем, я остановил процесс, пока системная память достигает 91%, диспетчер задач сообщает: 4G RAM в общей сложности, Cache – 329M и доступно 335MB. Тогда использование памяти останется вокруг этого уровня, пока я не перезагружу компьютер. Если я остановлю экземпляр проводника в диспетчере задач, экран будет пустым с индикатором жесткого диска все время и никогда не вернется. Обычно, когда я останавливаю экземпляр explorer в диспетчере задач, я могу повторно вызвать его, нажав Win + E, или он был перезапущен автоматически.

Ну, действительно приятное управление памятью!


[ИЗМЕНИТЬ СНОВА] Похоже, что некоторая часть использованной памяти вскоре была освобождена, но не все. Некоторые из памяти Cached и Available вернулись в диспетчере задач. Я больше не ждал, не знаю, что будет потом.

Техническое объяснение

Причина, по которой большинство методов вызывают проблемы, заключается в том, что 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 пытается перечислить файлы и папки перед их удалением, зависит от метода, который вы используете для их удаления, но как Explorer, так и интерпретатор команд (вы можете увидеть задержку при запуске команды). Вы также можете видеть активность диска (HDD LED), когда он считывает дерево каталогов с диска.

Решение

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

 @echo off if not [%1]==[] cd /d %1 del /q * for /d %%i in (*) do call %0 "%%i" 

Это делается для проверки того, прошел ли аргумент. Если это так, то он изменяется на указанный каталог (вы можете запустить его без аргумента для запуска в текущем каталоге или указать каталог – даже на другом диске, чтобы он начинался там).

Затем он удаляет все файлы в текущем каталоге. В этом режиме он не должен перечислять ничего и просто удалять файлы, не всасывая много, если таковые имеются, памяти.

Затем он перечисляет папки в текущем каталоге и называет себя, передавая каждую папку (self) для рекурсии вниз.

Анализ

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

Вы можете задаться вопросом об использовании ключа /r вместо использования (ручной) рекурсии. Это не сработает, потому что, в то время как /r переключатель выполняет рекурсию, он предварительно перечисляет все дерево каталогов, которое мы хотим избежать; Мы хотим удалить, как мы идем, не отслеживая.

сравнение

Давайте сравним этот метод с методом полного перечисления.

Вы сказали, что у вас «миллионы каталогов»; Скажем, 100 миллионов. Если дерево приблизительно сбалансировано и предполагает в среднем около 100 подкаталогов для каждой папки, то самый глубокий вложенный каталог будет примерно на четыре уровня вниз – на самом деле, во всем дереве будет 101,010,100 подпапок. (Забавно, как 100M может сломаться до 100 и 4.)

Поскольку мы не перечисляем файлы, нам нужно отслеживать не более 100 наименований каталогов на каждый уровень, для максимально 4 × 100 = 400 каталогов в любой момент времени.

Поэтому потребность в памяти должна быть ~ 206,25 КБ, хорошо в рамках любой современной (или иной) системы.

Контрольная работа

К сожалению (?) У меня нет системы с триллионами файлов в миллионах папок, поэтому я не могу ее протестировать (я думаю, что в конце концов, у меня было около ~ 800K файлов), поэтому кому-то придется попробовать Это.

Предостережение

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

Для удаления всех папок потребуется много времени, и вы не можете многое сделать с этим. Что вы можете сделать, это сохранить ваши данные и отформатировать диск. Это не оптимально, но он будет работать (и быстро).

Другим вариантом является, возможно, использование какого-либо дистрибутива Linux на живом компакт-диске, который можно читать из раздела NTFS. Из личного опыта я знаю, что имя rm -rf folderName может работать не менее 2 дней без сбоя системы с 2 ГБ ОЗУ. Это займет некоторое время, но, по крайней мере, это закончится.

Эмм .. Я не хочу знать, как ты создал так много.

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

Вы пробовали команду rmdir /s ? Пока он фактически удаляет файлы по мере их поиска, а не ждет на каждом из них, которые могут быть перечислены, он может работать.

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

Однако любой метод займет некоторое время.

Shift + Delete пропускает Корзину и может значительно ускорить работу.

Если это не работает (крайние случаи), попробуйте Fast Folder Eraser и / или Mass Directory Eraser

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

 fsutil behavior set DisableDeleteNotify 1 

Обратите внимание, что это изменение может повлиять на производительность на твердотельных накопителях и может предотвратить автоматическое и / или ручное восстановление SAN-дисков.

Я не могу говорить с триллионами файлов, но недавно я обнародовал старый общий файл, содержащий файлы ~ 1.8M, используя:

 robocopy EmptyTMPFolder FolderToDelete /MIR /MT:16 /ETA /R:30 /W:5 

«EmptyTMPFolder» – пустой локальный каталог. Параметр / MIR заставит цель выглядеть как источник (пустой).

Реальной выгодой для этого подхода была опция повтора (/ R: 30). Это позволило использовать все возможности подключения, которые могут возникнуть в ходе этого процесса. Локальные удаления могут не найти преимущества в этом подходе.

У меня нет конкретных тестов для сравнения времени, но я бы предпочел это по сравнению с некоторыми другими вариантами, предложенными b / c параметров повтора / ожидания. Удаление началось почти мгновенно.

Вероятно, ваш антивирус / вредоносные программы потребляют всю память, а затем разбивают систему.

У самой Windows нет проблемы с удалением огромного количества файлов, хотя она, конечно, медленнее, чем аналогичная операция для большинства файловых систем, отличных от Microsoft.

С тех пор у меня были подобные проблемы с 10 миллионами файлов, но на сервере 2003, чтобы удалить файлы, которые я использовал ftp server / client, и оставил клиенту удаление файлов и папок. Это медленное решение, но оно отлично работает.

Вероятно, у вас будет вторая проблема с MFT в NTFS, у которой нет решения, MFT – это массив, который в win 2003 (я не уверен, что Microsoft имеет решение после победы 2003 года) хранит все файлы поэтапно, так что С триллионами файлов размер будет сумасшедшим, в моем случае у MFT было 17 миллионов записей, а размер MFT был около 19 ГБ, всего 45000 файлов, я тестировал в других системах и выглядел как за 1 миллион записей, которые MFT будет Около 1 ГБ.

Вы можете проверить статус MFT с помощью этой команды:

Defrag c: / a / v

C: единичная буква / анализ / v verbose

Другое сложное решение, поскольку нет инструмента, который может сжать MFT, инструменты просто заполняют 0 именами файлов и свойств, но не более того, но вы можете использовать конвертер VMware или другой вид P2V и создавать виртуальную машину на основе Ваш сервер, таким образом, вы устраните все проблемы, связанные с MFT, я никогда не тестировал преобразование из V2P, теперь я работаю только в виртуальных средах, но я видел много информации об этом в Интернете.

Это победа 2003 года, теперь она отлично работает, размер MFT составляет 40 МБ, и все в порядке, если вы хотите, я могу рассказать вам больше о резервных копиях, дефрагментах или других задачах, связанных с миллионами крошечных файлов

Пытаясь использовать различные подходы к удалению более 10 миллионов файлов журнала слияния, я заметил, что в среднем 30 000 файлов в среднем можно было удалить за 10 минут. Это займет около 55 часов для 10 миллионов файлов …

Используя приведенный ниже сценарий, скорость удаления увеличилась на ~ 75%. Списки файлов создаются и выполняются параллельными процессами, увеличивая операции с дисками (но не линейно). Я показываю 4 вилки, но двух может хватить.

Существует возможность использовать PowerShell, что значительно сокращает время, необходимое для подготовки списков.

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

 @ECHO OFF SETLOCAL EnableDelayedExpansion IF /I "%~1"=="timestamp" ( CALL :ECHOTIMESTAMP GOTO END ) rem directory structure to delete SET "DELETE=c:\_delete\Content.IE5\???<<<change this>>>???" rem primary list of discovered files to delete SET "LIST=delete-list.txt" rem base path for sub-lists SET "LISTBASE=.\delete-list" SET "TITLE=Batch Delete Process" rem specifies number of batch delete processes to spawn SET FORKS=4 rem when set to 1, use PowerShell for list building and delete. Definitely improves time to build fork sublists SET POWERSHELL=0 rem specifies max files to delete when greater than 0 SET MAXDEL=1000000 rem prompt for confirmatoin SET /P CONT=About to delete all files and directories from !DELETE!. Continue (Y/N)? IF /I NOT "!CONT!"=="Y" EXIT /B CALL :ECHOTIMESTAMP ECHO Accumulating list of files to delete... dir /b /s "!DELETE!" > "!LIST!" FOR /F "delims=" %%c IN ('type "!LIST!" ^| find /C ":"') DO SET "COUNT=%%c" ECHO Discoverd !COUNT! files and directories to delete. IF %MAXDEL% GTR 0 IF !COUNT! GTR %MAXDEL% ( SET COUNT=%MAXDEL% ECHO Limiting files/directories deletion count to !COUNT! ) CALL :ECHOTIMESTAMP ECHO Preparing !FORKS! delete processes... SET /A LIMIT=!COUNT!/!FORKS! IF !POWERSHELL! EQU 1 ( SET SKIP=0 FOR /L %%n IN (1,1,!FORKS!) DO ( SET "CURRENT=!LISTBASE!-%%n.txt" SET "LIST[%%n]=!CURRENT!" DEL /f /q "!CURRENT!" > nul 2>&1 IF %%n EQU !FORKS! SET /A LIMIT+=!FORKS! SET CMD=type \"!LIST!\" ^| select -first !LIMIT! -skip !SKIP! powershell -command "& {!CMD!}" > "!CURRENT!" SET /A SKIP+=!LIMIT! ) ) ELSE ( rem significantly slower but no PowerShell. SET L=1 SET N=!LIMIT! SET C=0 FOR /F %%f IN (!LIST!) DO ( IF !C! LSS !COUNT! ( IF !N! GEQ !LIMIT! ( SET "CURRENT=!LISTBASE!-!L!.txt" SET "LIST[!L!]=!CURRENT!" DEL /f /q "!CURRENT!" > nul 2>&1 SET /A L+=1 SET /AN=0 ) ELSE ( SET /A N+=1 ) ECHO %%f >> "!CURRENT!" ) ELSE ( GOTO ENDLIST ) SET /A C+=1 ) ) :ENDLIST CALL :ECHOTIMESTAMP ECHO Forking !FORKS! delete processes... FOR /L %%t IN (1,1,!FORKS!) DO ( SET "CURRENT=!LIST[%%t]!" IF !POWERSHELL! EQU 1 ( SET "TAB= " SET BLANK=!TAB!!TAB!!TAB!!TAB!!TAB!!TAB!!TAB!!TAB! SET BLANK=!BLANK!!BLANK!!BLANK!!BLANK! SET DEL_CMD=del -force -recurse -ea SilentlyContinue -path \"$_\" SET $W_CMD=$w=$Host.UI.RawUI.WindowSize.Width SET $S_CMD=$s=\"$_\";$i=[math]::max^(0,$s.length-$w^);$s=$s.substring^($i, $s.length-$i^);$s=\"$s !BLANK!\";$s=$s.substring^(0,[math]::min($w,$s.length^)^) SET ECHO_CMD=Write-Host \"`r$s\" -NoNewLine SET CMD=type \"!CURRENT!\" ^| %% {!DEL_CMD!; !$W_CMD!; !$S_CMD!; !ECHO_CMD!} SET CMD=powershell -command "^& {!CMD!}" ^& ECHO\ ^& "%~dpnx0" timestamp ECHO CMD !CMD! ) ELSE ( SET LOOP=FOR /F %%%f IN ^(!CURRENT!^) DO SET OP=del "%%%f" SET [email protected] OFF ^&^& ^(!LOOP! !OP! ^> nul 2^>^&1 ^) ^& "%~dpnx0" timestamp ) rem ECHO !CMD! START "!TITLE! %%t" cmd /k !CMD! ) GOTO END :ECHOTIMESTAMP SETLOCAL SET DATESTAMP=!DATE:~10,4!-!DATE:~4,2!-!DATE:~7,2! SET TIMESTAMP=!TIME:~0,2!-!TIME:~3,2!-!TIME:~6,2! ECHO !DATESTAMP: =0!-!TIMESTAMP: =0! ENDLOCAL GOTO :EOF :END ENDLOCAL EXIT /B 

Попробуйте это и измените, как вам нужно.

Это проверенный сценарий на Win2003 на основе технических объяснений и анализа Synetech ответил 15 октября 13 в 15:22

 @echo off rem ### USE FULL PATH AS FIRST ARGUMENT TO SCRIPT, DONT FORGET QUOTES ! rem ### If you move this script, fix script path variable... SET STATICFULLSCRIPTPATH="D:\scripts\FOLDER" SET SCRIPTNAME="DeleteFast.bat" rem ### If CD fails or IF condition has problems, rem ### and DEL or RMDIR runs, its better to be at safe place. if not exist "%TEMP%\SAFE" mkdir "%TEMP%\SAFE" if exist "%TEMP%\SAFE" cd /d "%TEMP%\SAFE" rem ### Fix quote overflow set var1="%1" set var1=%var1:"=% if not [%1]==[] ( cd /d "%var1%" echo # KILLING F AT : "%var1%" rem ### uncomment to do damage! ### rem # del /f/q * > nul for /d %%i in (*) do call "%STATICFULLSCRIPTPATH%\%SCRIPTNAME%" "%var1%\%%i" rem ## Finish deleting the last dir cd /d "%var1%\.." echo # KILLING DIR : "%var1%" rem ## Remove dir.. first try rmdir /q "%var1%" if exist "%var1%" ( rem ## Remove dir.. second try rem ## If thousands of files/dirs had permission/ownership problems, then prepare to wait a long time. rem ### uncomment to do damage! ### rem #cmd.exe /c takeown /f "%var1%" && icacls "%var1%" /grant SOMEBODY:F rem ### uncomment to do damage! ### rem #rmdir /s/q "%var1%" ) ) cd /d "%STATICFULLSCRIPTPATH%" 

Testrun .. Есть папки, такие как A1-A4, B1-B4 и C1-C4, вложенные по-разному ..

 Z:\>"D:\scripts\FOLDER\DeleteFast.bat" "D:\scripts\TESTF\DIRS" # KILLING F AT : "D:\scripts\TESTF\DIRS" # KILLING F AT : "D:\scripts\TESTF\DIRS\A1" # KILLING F AT : "D:\scripts\TESTF\DIRS\A1\B1" # KILLING F AT : "D:\scripts\TESTF\DIRS\A1\B1\C 1" # KILLING DIR : "D:\scripts\TESTF\DIRS\A1\B1\C 1" # KILLING DIR : "D:\scripts\TESTF\DIRS\A1\B1" # KILLING F AT : "D:\scripts\TESTF\DIRS\A1\B2" # KILLING F AT : "D:\scripts\TESTF\DIRS\A1\B2\C 2" # KILLING DIR : "D:\scripts\TESTF\DIRS\A1\B2\C 2" # KILLING DIR : "D:\scripts\TESTF\DIRS\A1\B2" # KILLING DIR : "D:\scripts\TESTF\DIRS\A1" # KILLING F AT : "D:\scripts\TESTF\DIRS\A2" # KILLING F AT : "D:\scripts\TESTF\DIRS\A2\B3" # KILLING F AT : "D:\scripts\TESTF\DIRS\A2\B3\C 3" # KILLING DIR : "D:\scripts\TESTF\DIRS\A2\B3\C 3" # KILLING DIR : "D:\scripts\TESTF\DIRS\A2\B3" # KILLING DIR : "D:\scripts\TESTF\DIRS\A2" # KILLING F AT : "D:\scripts\TESTF\DIRS\A3" # KILLING F AT : "D:\scripts\TESTF\DIRS\A3\B4" # KILLING F AT : "D:\scripts\TESTF\DIRS\A3\B4\C 4" # KILLING DIR : "D:\scripts\TESTF\DIRS\A3\B4\C 4" # KILLING DIR : "D:\scripts\TESTF\DIRS\A3\B4" # KILLING DIR : "D:\scripts\TESTF\DIRS\A3" # KILLING F AT : "D:\scripts\TESTF\DIRS\A4" # KILLING DIR : "D:\scripts\TESTF\DIRS\A4" # KILLING DIR : "D:\scripts\TESTF\DIRS" D:\scripts\FOLDER> 

Я не могу комментировать (сайт жалуется на мою репутацию), поэтому я добавляю свой комментарий здесь.

Решение Bjv создает неудобные временные файловые списки. И затем повторяет их второй раз, чтобы выполнить фактическую работу. https://superuser.com/a/892412/528695

Оригинальный сценарий Synetech не работал для меня. https://superuser.com/a/416469/528695

 @echo off if not [%1]==[] cd /d %1 echo "%1" for /d %%i in (*) do call %0 "%%i" 

Результаты..

 Z:\>C:\privscripts\TESTF\DeleteFastORIGINAL.bat "C:\privscripts\TESTF\DIRS" ""C:\privscripts\TESTF\DIRS"" ""A1"" ""B1"" ""C1"" The system cannot find the path specified. ""B2"" The system cannot find the path specified. ""A2"" The system cannot find the path specified. ""A3"" The system cannot find the path specified. ""A4"" C:\privscripts\TESTF\DIRS\A1\B1\C1> 

В этом ответе на StackOverflow используется комбинация del и rmdir :

 del /f/s/q foldername > nul rmdir /s/q foldername 

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

  find dir \! -type d | sed 's/^/rm /' | sh 

Сценарий выполняется, даже когда он сгенерирован, и нет циклов, поэтому оболочка (надеюсь) не должна создавать большие файлы temp. Это займет некоторое время, так как сценарий длится миллионы строк. Возможно, вам придется настроить команду rm (возможно, я должен был использовать -f ?, но вы понимаете ваши файлы лучше меня), чтобы заставить ее работать.

Теперь у вас нет ничего, кроме каталогов. Вот где вещи становятся плавными. Возможно, вы удалили достаточно файлов, чтобы вы могли делать rm -rf без rm -rf памяти (и это, вероятно, будет быстрее, чем другой скрипт). Если нет, мы можем адаптировать этот ответ Stackoverflow :

  find dir | perl -lne 'print tr:/::, " $_"' | sort -n | cut -d' ' -f2 | sed 's/^/rmdir /' | sh 

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

Проблема, с которой вы можете столкнуться, заключается в том, что каталог не уплотняется при удалении файла / папки, поэтому, если у вас есть папка с 1 миллионом файлов и удалите первые 500 тысяч из них. В начале вашего каталога есть тонна блоков, которые для всех намерений пустые.

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

Еще одна вещь, которую вы можете попробовать, – использовать сторонний инструмент, например «PerfectDisk» для компактных папок, после удаления нескольких файлов.

Некоторое время назад я столкнулся с тем же вопросом. Я написал небольшую утилиту, которая делает именно это: рекурсивно удаляет каталог. Он не будет перечислять файлы и не будет потреблять много памяти (O (n + m) с max с n = максимальная глубина каталога и m = максимальное количество файлов / каталогов в одном из поддиректоров). Он может обрабатывать длинные файловые пути (> 256 символов). Я хотел бы получить обратную связь, если вы сможете решить свою проблему с этим.

Вы можете найти его здесь: https://github.com/McNetic/fdeltree (исполняемый файл в папке выпусков)

  • Необходимо удалить все файлы с одним расширением на диске в Windows 7
  • Скопировать полный путь к файлу в Windows XP
  • Как установить программу по умолчанию для открытия файлов без расширения в Windows?
  • Создать список файлов / папок
  • Есть ли способ по-настоящему удалить все удаленные файлы?
  • Принудительное удаление каталога под Win 7
  • Как безопасно удалять файлы, хранящиеся на SSD?
  • Не удается удалить файл: система не может найти указанный файл
  • Как найти все файлы, содержащие только нулевые байты (любое их число)
  • Как сохранить атрибуты файлов при копировании файлов в Windows?
  • Что делает «подготовка к копированию»?
  • Давайте будем гением компьютера.