This script is particularly useful for taking advantage of processor and spindle performance when synchronizing directories that contain hundreds or thousands of subdirectories.
@echo off cls color 2a title Multi-Threaded Robocopy SETLOCAL ENABLEDELAYEDEXPANSION :: Ben Kendall's Multi-Threaded Robocopy :: Copyright April 2011 :: :: Kicks off a robocopy instance for every processor on your machine :: Monitors for termination of robocopy instances and spawns new ones to take their place :: :: Robocopy.exe must be somewhere in PATH - Already the case in newer versions of Windows :: :: Change variables below to suit your needs :: :: http://www.tech-recipes.com/rx/13768/multi-threaded-robocopy-by-first-level-subfolder/ set SOURCE=%systemdrive%\temp set DEST=%systemdrive%\testdir set OPTS=/mir /np /w:3 /r:3 set /a THREADS=%NUMBER_OF_PROCESSORS% echo. echo Copying %THREADS% folders at a time from "%SOURCE%" to "%DEST%" echo. echo With options "%OPTS%" echo. pause set FOLDER=0 set FOLDERNUM=0 set RUNCOUNT=0 :: Kick off primary loop that iterates through directories under %SOURCE%: for /f "tokens=* delims=" %%a in ('dir /a:d /b "%SOURCE%"') do ( set FOLDER=%%a :STARTLOOP if !RUNCOUNT! LSS %THREADS% ( call :WORK ) else ( call :KILLTIME ) ) :: Finished primary loop so folder copies are done: goto :DONE :: Spawn a robocopy thread and increment our count: :WORK set /a RUNCOUNT=!RUNCOUNT!+1 set /a FOLDERNUM=!FOLDERNUM!+1 echo. echo Folder number !FOLDERNUM! is: "%SOURCE%\%FOLDER%" start "Robocopy Folder Number:!FOLDERNUM!" robocopy.exe "%SOURCE%\%FOLDER%" "%DEST%\%FOLDER%" %OPTS% goto :EOF :: Robocopy threads are currently running so we wait and check again before spawning new: :KILLTIME call :GETRUNNING if %RUNCOUNT% LSS %THREADS% ( goto :WORK ) else ( goto KILLTIME ) ::::::::::::: :: Subroutine to get count of running instances of robocopy.exe: :GETRUNNING ping -n 6 localhost >nul set RUNCOUNT=0 for /f "tokens=1 delims=," %%b in ('tasklist /fo csv /nh /fi "imagename eq robocopy.exe"^| findstr /v "INFO:"') do ( set /a RUNCOUNT=!RUNCOUNT!+1 ) goto :EOF ::End of GETRUNNING subroutine ::::::::::::: :DONE :: Robocopy remaining files that live in root of source directory: :COPYFILES echo. echo Copying remaining files from "%SOURCE%" to "%DEST%"... start "Robocopy Files in %SOURCE%" /wait robocopy.exe "%SOURCE%" "%DEST%" /purge /np /w:3 /r:3 :ALLDONE :: Check for remaining instances of robocopy.exe and wait for completion before continuing: call :GETRUNNING if .%RUNCOUNT%. NEQ .0. (goto :ALLDONE) echo. echo Done echo. echo We stopped Copying at folder "%SOURCE%\%FOLDER%" echo. pause set SOURCE= set DEST= set OPTS= set THREADS= set RUNCOUNT= set FOLDER= set FOLDERNUM= ENDLOCAL goto :END :END