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