Wie bekomme ich zusammenfassende Informationen zur Robokopie in Powershell?

7

Ich habe ein schnelles Skript geschrieben, um Dateidifferenzen zwischen Servern zu vergleichen und dann eine Aufforderung zu geben, ob die Änderungen gespiegelt werden sollen. Ich möchte, dass es intelligent NICHT zum Kopieren auffordert, wenn es keine Änderungen gibt.

Das Skript:

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!" }

Ich möchte, dass Powershell nicht darum bittet, fortzufahren, wenn Robocopy 0 für Nichtübereinstimmung, Fehlgeschlagen, Extras und Kopiert meldet. Es ist nicht sehr wichtig für dieses spezielle Projekt, aber ich kann mir ein paar nützliche Verwendungszwecke für eine solche Überprüfung vorstellen. Vielen Dank!

jski
quelle

Antworten:

6

Endlich etwas, was die Leute nicht in 10 Sekunden beantwortet haben! Ich habe Ihr Problem genutzt, um mehr über Powershell zu erfahren. Folgendes funktioniert für mich, ich hoffe zu sehen, wie andere diesen Code verkleinern werden:

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" }

Hinweis: Ich habe den regulären Ausdruck oben von einem Punkt in ein Leerzeichen unmittelbar vor dem Sternchen geändert. Dies eliminiert das Risiko, "Dateien" oder "Verzeichnisse" oder "Summen" in einem Dateinamen / Pfad abzufangen. Die ursprüngliche Zeile ist unten für die Nachwelt.
jski 16.07.2014

$ robo_results = $ robo_test -match '^ (? =. ? \ b (Gesamt | Dirs | Dateien) \ b) ((?! Dateien).) $'

Lars
quelle
1
Was ist eine effizientere Methode, um die Ganzzahlen aus der Robocopy-Trockenlaufausgabe zu ermitteln? Die mehrfachen Manipulationen derselben Daten haben mich gestört, aber ich kannte keinen anderen Weg, dies zu tun. Vielen Dank,
Lars
Ihren Beitrag bearbeitet, um einen möglichen Fehler bei bestimmten Dateinamen zu vermeiden.
Jski
2

Mir ist klar, dass dies ein älterer Thread ist, aber beachten Sie, dass dies auch mithilfe des von robocopy zurückgegebenen Exit-Codes erreicht werden kann, um festzustellen, ob Änderungen vorhanden sind (ein Wert von 0 zeigt an, dass keine Änderungen vorgenommen wurden). Es gibt zwei Möglichkeiten, dies zu tun:

  1. Führen Sie Ihre obige Robocopy-Anweisung aus und überprüfen Sie in der nächsten Zeile den Wert von $ LastExitCode.
  2. Start-Prozess verwenden:
$ RobocopyResult = Start-Prozess -FilePath robocopy -ArgumentList $ RobocopyParams -Wait -PassThru
$ RobocopyResult.ExitCode

Wenn Sie Start-Process verwenden, ist es wichtig, -PassThru zu verwenden, da sonst in $ RobocopyResult kein Wert festgelegt wird.

Weitere Exit-Codes finden Sie unter http://ss64.com/nt/robocopy-exit.html .

Aakash Shah
quelle
0

Hier ist mein Hack dazu. Mein Code liest die Protokolldatei und sucht nach den Zeilen, die den Zusammenfassungsfeldern entsprechen. Anschließend wird es in zwei Objekte analysiert, die die Statistiken für Dateien und Verzeichnisse enthalten:

        ### Read data from log summary at end of RoboCopy log
        $Props = ((cat $RoboCopyLogFile | ? {$_ -like "*Total*Copied*Skipped*Mismatch*FAILED*Extras*"}) | select -Last 1).split(" ") | ? {$_ -match "a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z"}
        $Dirs = (((cat $RoboCopyLogFile | ? {$_ -like "*Dirs : *"})) | select -Last 1).split(" ") | ? {$_ -match "1|2|3|4|5|6|7|8|9|0"}
        $Files = (((cat $RoboCopyLogFile | ? {$_ -like "*Files : *"})) | select -Last 1).split(" ") | ? {$_ -match "1|2|3|4|5|6|7|8|9|0"}
        ### Loop through the propteries of the summary
        $i = 0
        $FileStats = @{}
        $DirStats = @{}
        foreach($Prop in $Props)
        {
            $FileStats.("$Prop") = $Files[$i]
            $DirStats.("$Prop") = $Dirs[$i]
            $i++
        }
        $FileStats = New-Object -TypeName psobject -Property $FileStats
        $DirStats = New-Object -TypeName psobject -Property $DirStats
Jason
quelle