Skip to content

Instantly share code, notes, and snippets.

@stefanprodan
Created April 16, 2015 20:02
Show Gist options
  • Save stefanprodan/846f6bd233678fd05e33 to your computer and use it in GitHub Desktop.
Save stefanprodan/846f6bd233678fd05e33 to your computer and use it in GitHub Desktop.
Solution to delete millions of files on windows, after starting the script kill explorer.exe process. Script source http://superuser.com/a/892412/376959
@ECHO OFF
SETLOCAL EnableDelayedExpansion
IF /I "%~1"=="timestamp" (
CALL :ECHOTIMESTAMP
GOTO END
)
rem directory structure to delete
SET "DELETE=c:\_delete\???<<<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 /A N=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 CMD=@ECHO 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment