How to get robocopy summary information involved in powershell?
I have a quick script written to compare file differences across servers, and then give a prompt for whether to mirror the changes. I'd like it to intelligently NOT prompt for copying if there aren't any changes.
The script:
robocopy "$cSource" "$cDestination" /E /L /FP
$cDecision = Read-host "Continue = 1, anything else = Stop"
if ($cDecision -eq "1") {
robocopy "$cSource" "$cDestination" /MIR /FFT /Z /W:5 /MT:64 /XX /log:$cLogLocation
Invoke-item $cLogLocation
}
else { Write-host "Quit!" }
I'd like to have Powershell not ask to continue if Robocopy reports 0 for Mismatch, Failed, Extras, and Copied. It's not very important for this particular project, but I can think of a couple useful uses for such a check. Thanks!
Solution 1:
Finally something people didn't answer in 10 seconds! I used your issue to continue to learn more about Powershell. The following works for me, I hope to see how others will slim down this code:
Clear-Host
$ErrorActionPreference = "Continue"
$DebugPreference = "Continue"
$VerbosePreference = "Continue"
@"
## robocopy_helper.ps1 ########################################################
Usage: powershell -ExecutionPolicy Bypass -File ./robocopy_helper.ps1
Purpose: Dry run before Full run of robocopy
History: 07/11/2014 - Created
###############################################################################
"@
## User Supplied Variables
$cSrc = "C:\Temp"
$cDst = "C:\Temp2"
$cLog = "c:\robo.log"
## Robocopy Dry Run
$robo_test = robocopy "$cSrc" "$cDst" /E /L /FP
## Use Regular Expression to grab the following Table
# Total Copied Skipped Mismatch FAILED Extras
# Dirs : 1 0 1 0 0 0
# Files : 1 0 1 0 0 0
$robo_results = $robo_test -match '^(?= *?\b(Total|Dirs|Files)\b)((?! Files).)*$'
## Convert Table above into an array
$robo_arr = @()
foreach ($line in $robo_results){
$robo_arr += $line
}
## Create Powershell object to tally Robocopy results
$row = "" |select COPIED, MISMATCH, FAILED, EXTRAS
$row.COPIED = [int](($robo_arr[1] -split "\s+")[4]) + [int](($robo_arr[2] -split "\s+")[4])
$row.MISMATCH = [int](($robo_arr[1] -split "\s+")[6]) + [int](($robo_arr[2] -split "\s+")[6])
$row.FAILED = [int](($robo_arr[1] -split "\s+")[7]) + [int](($robo_arr[2] -split "\s+")[7])
$row.EXTRAS = [int](($robo_arr[1] -split "\s+")[8]) + [int](($robo_arr[2] -split "\s+")[8])
## If there are differences, lets kick off robocopy again
if ( ($row.COPIED + $row.MISMATCH + $row.FAILED + $row.EXTRAS) -gt 0 ){
robocopy "$cSrc" "$cDst" /MIR /FFT /Z /W:5 /MT:64 /XX /log:$cLog
Invoke-item $cLog
}
else { Write-host "Folders '$cSrc' and '$cDst' are twins" }
Note: I have changed the regular expression above from a period to a space immediately before the asterisk. This eliminates the risk of catching 'files' or 'dirs' or 'totals' in a filename/path. The original line is below for posterity.
jski 2014/07/16
$robo_results = $robo_test -match '^(?=.?\b(Total|Dirs|Files)\b)((?! Files).)$'
Solution 2:
I realize that this is an older thread, but note that this can also be accomplished using the exit code returned by robocopy to determine whether any changes exist (a value of 0 indicates no changes). There are 2 ways to do this:
- Run your robocopy statement above, and then in the next line, check the value of $LastExitCode.
- Use Start-Process:
$RobocopyResult = Start-Process -FilePath robocopy -ArgumentList $RobocopyParams -Wait -PassThru $RobocopyResult.ExitCode
If using Start-Process, it is important to use -PassThru, otherwise no value will be set in $RobocopyResult.
Other exit codes are listed at http://ss64.com/nt/robocopy-exit.html.