Functions/Invoke-ParallelRobocopy.ps1
function Invoke-ParallelRobocopy { [CmdletBinding()] param ( [Parameter(Mandatory)] [string] $Source, [Parameter(Mandatory)] [string] $Destination, [Parameter()] [string] $ExcludeDirectories, [Parameter()] [int] $MaxParallelJobs = 2 ) if ($Source[-1] -eq "\") { $Source = $Source.Substring(0, ($Source.Length - 1)) } if ($Destination[-1] -eq "\") { $Destination = $Destination.Substring(0, ($Destination.Length - 1)) } Write-Verbose $Source Write-Verbose $Destination $dirs = Get-ChildItem $Source -Directory if ($ExcludeDirectories) { $dirs = $dirs | Where-Object Name -NotMatch $ExcludeDirectories } Write-Verbose ($dirs | Format-Table | Out-String) $processRc = @{} $dirs | ForEach-Object { $i++ $subSource = $_.FullName $subDestination = Join-Path $Destination $_.Name $processRc[$i] = Start-Process -FilePath "robocopy.exe" -ArgumentList "`"$($subSource)`" `"$($subDestination)`" /MIR /NFL /NDL /W:1 /R:1 /MT:32" -PassThru -WindowStyle Minimized while (($processRc | ForEach-Object { $_.Values | Where-Object HasExited -EQ $false }).count -ge $MaxParallelJobs) { Write-Warning "Waiting to finish $(($processRc | ForEach-Object { $_.Values | Where-Object HasExited -EQ $false }).count) robocopy jobs" Start-Sleep 1 } } while ($processRc | ForEach-Object { $_.Values | Where-Object HasExited -EQ $false }) { Write-Warning "Waiting to finish $(($processRc | ForEach-Object { $_.Values | Where-Object HasExited -EQ $false }).count) robocopy jobs before final sync" Start-Sleep 1 } Start-Process -FilePath "robocopy.exe" -ArgumentList "`"$($Source)`" `"$($Destination)`" /MIR /NFL /NDL /W:1 /R:1 /MT:128 /XD $($ExcludeDirectories)" -NoNewWindow -Wait } |