sugram
Goto Top

Powershell mehrere Dateien vergleichen

Hallo

Ich möchte von unterschiedlichen PC's gewisse Dateien in einem Verzeichniss vergleichen.
Dies soll dann ermitteln ob die Dateien ein unterschiedliches Datum haben.
In den Verzeichnissen, werden Programmteile abgespeichert, die manchmal zuerst auf einen PC getestet werden und erst danach verteilt werden.

Aktuell ermittle ich mit einer Batch den Inhalt der Verzeichnisse und gebe diese dann in einem File aus.

for /F "delims=" %%i in ('"dir /s /b /a-d "\\Sharename1\xyz\123\*.pvg" "') do (echo %%~nxi %%~ti >> c:\tmp\1\PC1)  
for /F "delims=" %%i in ('"dir /s /b /a-d "\\Sharename2\xyz\123\*.pvg" "') do (echo %%~nxi %%~ti >> c:\tmp\1\PC2)  
usw.

Jetzt wollte ich mittels einer Powershell den Inhalt der Dateien vergleichen und bei einem Unterschied soll er eine Email senden.
Das klappt auch mit 2 Dateien.

$PVG1 = Compare-Object (get-content $path$file1) (get-content $path$file2 ) -CaseSensitive -PassThru | where {$_.SideIndicator -eq '<='}  
$PC1 = Compare-Object ($file1) ($file2 ) -CaseSensitive -PassThru | where {$_.SideIndicator -eq '<='}  
#$PVG2 = Compare-Object (get-content $path$file1) (get-content $path$file3 ) -CaseSensitive -PassThru | where {$_.SideIndicator -eq '<='} 
#$PC2 = Compare-Object ($file1) ($file3 ) -CaseSensitive -PassThru | where {$_.SideIndicator -eq '<='} 
Write-Host $PVG1
Write-Host $PC1
Write-Host $PVG2
Write-Host $PC2

Send-MailMessage –To "Emailr@xy.123.com" `  
                   –Subject ("ACHTUNG PVG DATEI '$PVG1' UNTERSCHIEDLICH!")`  
                   –Body ("Die PVG '$PVG1' ist auf dem PC '$PC1' unterschiedlich")`  
                   –SmtpServer "smtpcom" `  
                   –From "noreplay@domain.com" `  
                   -encoding ([System.Text.Encoding]::UTF8)       

Das klappt auch soweit.
Aber wie kann ich hier 3 oder mehrere Files auf einmal überprüfen und dann eine einzige Email senden, in der dann nur der PC entahlten ist wo sich der Unterschied befindet?

Mir ist klar das man dies eleganter lösen könnte, aber ich bin schon mal froh, daß ich das soweit hinbekommen habe.

Bin für jede Hilfe Dankbar.

Content-ID: 841038546

Url: https://administrator.de/contentid/841038546

Ausgedruckt am: 17.11.2024 um 19:11 Uhr

Doskias
Doskias 28.06.2021 um 15:42:04 Uhr
Goto Top
Moin,

was spricht gegen ein get-childitem in Verbindung mit einer for each-Schleife?

Gruß
Doskias
sugram
sugram 28.06.2021 um 15:50:36 Uhr
Goto Top
Wahrscheinlich nicht's.
Da muss ich mir dann erst das mit dem get-childitem ansehen.
Und vor allem das mit der Schleife face-wink
Bin in Powershell noch totaler Anfänger.
Doskias
Doskias 28.06.2021 um 15:58:44 Uhr
Goto Top
Zitat von @sugram:
Bin in Powershell noch totaler Anfänger.

Waren wir alle mal. Ich weiß jetzt nicht genau was du im Detail vor hast, aber vielleicht ist dir auch mit Compare-Object schon geholfen
colinardo
Lösung colinardo 28.06.2021 aktualisiert um 18:45:59 Uhr
Goto Top
Servus @sugram,
da führen viele Wege nach Rom aber von der Ausgabe in Textdateien solltest du dich endgültig verabschieden, das war schon zu Batch-Zeiten ein unnötiger Workaround und mit Powershell erst recht nicht mehr nötig.

Habe dir hier mal 3 unterschiedliche Varianten zum Vergleichen von Verzeichnis-Inhalten aufgeführt. Das Send-MailMessage habe ich hier jetzt weggelassen, denke das sollte sich von selbst erklären wo du es einbauen musst face-wink.

back-to-topEinfacher Vergleich eines Referenz-Ordners mit mehreren anderen Ordnern mittels der Properties Name und LastWriteTime

# Referenzordner
$ref_dir = 'D:\Referenzordner'  
# Dateifilter
$filefilter = '*.pvg'  
# Ordner die zu vergleichen sind
$shares = "\\Sharename1\xyz\123","\\Sharename2\xyz\123"  
# Dateien des Referenzordners auflisten
$ref = ls $ref_dir -File -Filter $filefilter
# für jeden Ordner im Array ...
foreach ($share in $shares){
    # vergleiche den Referenzordner mit dem in der Schleife aktuellen anhand Name und LastWriteTime
    $diff = compare @($ref) @(ls $share -File -Filter $filefilter) -Property Name,LastWriteTime
    # wenn es Unterschiede gibt ...
    if ($diff){
        "'$share' hat unterschiedliche Dateien"  
        $diff | ft -AutoSize
    }
}

back-to-topVergleich eines Referenz-Ordners mit mehreren anderen Ordnern mittels Datei-Hashes

# Referenzordner
$ref_dir = 'D:\Referenzordner'  
# Dateifilter
$filefilter = '*.pvg'  
# Ordner die zu vergleichen sind
$shares = "\\Sharename1\xyz\123","\\Sharename2\xyz\123"  
# Hashes für alle Dateien im Referenzordner ermitteln und Property für Name hinzufügen
$ref = Get-FileHash "$ref_dir\$filefilter" -Algorithm SHA256 | select Hash,@{n='Name';e={split-path $_.Path -Leaf}}  
# für jeden Ordner im Array ...
foreach($share in $shares){
    # Hashes des zu vergleichenden Ordners berechnen lassen und Property für Name hinzufügen
    $dir_hashes = Get-FileHash "$share\$filefilter" | select Hash,@{n='Name';e={split-path $_.Path -Leaf}}  
    # vergleiche die Hashes/Dateinamen
    $diff = compare @($ref) @($dir_hashes) -Property Name,Hash
    # wenn es Unterschiede gibt ...
    if ($diff){
       "'$share' hat unterschiedliche Dateien"  
       $diff | ft -AutoSize
    }
}

back-to-topVergleich eines Referenz-Ordners mit mehreren anderen Ordnern mit der Hilfe von Robocopy im Simulationsmodus

# Referenzordner
$ref_dir = 'D:\Referenzordner'  
# Dateifilter
$filefilter = '*.pvg'  
# Ordner die zu vergleichen sind
$shares = "\\Sharename1\xyz\123","\\Sharename2\xyz\123"  
# für jeden Ordner im Array ...
foreach($share in $shares){
    # Unterschiede zwischen Referenz und aktuellem Ordner mittels Robocopy ermitteln (Leerzeilen werden aus der Ausgabe entfernt und führenden Whitspace entfernt)
    $diff = robocopy $ref_dir $share $filefilter /l /NDL /NJS /NJH /NC /NS /FP | ?{$_ -notmatch '^\s*$'} | %{$_ -replace '^\s*'}  
    # wenn es Unterschiede gibt ...
    if ($diff.count -gt 0){
        "'$share' hat unterschiedliche Dateien"  
        $diff
    }
}

Bin in Powershell noch totaler Anfänger.
Da haben wir hier genau das richtige für dich, frisch aus dem Backofen: Powershell Link-Leitfaden für Anfänger

Viel Erfolg!
Grüße Uwe
sugram
sugram 28.06.2021 aktualisiert um 16:59:24 Uhr
Goto Top
Zitat von @colinardo:


Bin in Powershell noch totaler Anfänger.
Da haben wir hier genau das richtige für dich, frisch aus dem Backofen: Powershell Link-Leitfaden für Anfänger

Viel Erfolg!
Grüße Uwe

Vielen Dank für den Input!
Da muss ich mich dann mal damit beschäftigen face-wink

Das
Einfacher Vergleich eines Referenz-Ordners mit mehreren anderen Ordnern mittels der Properties Name und LastWriteTime

klappt schon mal ganz gut, muss nur noch hinbekommen, daß er mir die unterschiedlichen Dateien ausgibt.
Aber sonst schaut das schon sehr vielversprechend aus
colinardo
colinardo 28.06.2021 aktualisiert um 18:46:15 Uhr
Goto Top
Zitat von @sugram:
Das
Einfacher Vergleich eines Referenz-Ordners mit mehreren anderen Ordnern mittels der Properties Name und LastWriteTime

klappt schon mal ganz gut, muss nur noch hinbekommen, daß er mir die unterschiedlichen Dateien ausgibt.
Aber sonst schaut das schon sehr vielversprechend aus
Die sind doch schon jeweils in der Variablen $diff gespeichert face-smile.

Btw. hatte einen kleinen Variablen-Schreibfehler Fehler in den Scripts korrigiert, als ich Variablen umbenannt hatte.
sugram
sugram 28.06.2021 um 20:34:42 Uhr
Goto Top
Zitat von @colinardo:

Die sind doch schon jeweils in der Variablen $diff gespeichert face-smile.

Btw. hatte einen kleinen Variablen-Schreibfehler Fehler in den Scripts korrigiert, als ich Variablen umbenannt hatte.

Danke für den Hinweis und deine Unterstützung!
Jetzt muss ich aber doch noch ein paar Files aus der Suche ignorieren.
Aber ich bekomme das mit dem Parameter -exclude nicht hin?!
Ist das nicht
ls $ref_dir -File -Filter $filefilter -exclude *123456*

?!
colinardo
Lösung colinardo 28.06.2021 aktualisiert um 20:59:28 Uhr
Goto Top
Zitat von @sugram:
Jetzt muss ich aber doch noch ein paar Files aus der Suche ignorieren.
Aber ich bekomme das mit dem Parameter -exclude nicht hin?!
Ist das nicht
> ls $ref_dir -File -Filter $filefilter -exclude *123456*
> 

?!
Nicht ganz bei Parameter Exclude muss man im Pfad-Parameter zusätzlich noch ein Wildcard setzen damit er das Exclude auch akzeptiert (MS hat das hier leider in bestimmten Konstellationen bei Get-ChildItem nicht so klar umgesetzt)
$ref = ls "$ref_dir\*" -File -Filter $filefilter -exclude '*123456*'  
Wenn es in den Zielordnern auch noch solche Files gibt musst du die beim ls Aufruf in der Schleife natürlich ebenso excluden, sonst würde er ja jeden Ordner melden indem solche Files liegen würden.

Wenns das dann war, den Beitrag bitte noch auf gelöst setzen, und Lösungen markieren. Merci.
sugram
sugram 29.06.2021 aktualisiert um 14:30:43 Uhr
Goto Top
Zitat von @colinardo:

Nicht ganz bei Parameter Exclude muss man im Pfad-Parameter zusätzlich noch ein Wildcard setzen damit er das Exclude auch akzeptiert (MS hat das hier leider in bestimmten Konstellationen bei Get-ChildItem nicht so klar umgesetzt)
> $ref = ls "$ref_dir\*" -File -Filter $filefilter -exclude '*123456*'  
> 

Ahhh, daß war ein super hinweis.
Damit klappt das auch einwandfrei face-smile

Vielen Dank dafür

Aber das mit den Dateinamen bekomme ich nicht hin?!

Die sind doch schon jeweils in der Variablen $diff gespeichert face-smile.

Wenn ich mir nun dafür eine Email senden lasse, erhalte ich zwar den UNC Pfad, aber nicht den Dateinamen

foreach ($share in $shares){
    # vergleiche den Referenzordner mit dem in der Schleife aktuellen anhand Name und LastWriteTime
    $diff = compare @($ref) @(ls "$share\*" -File -Filter $filefilter -exclude '*Cali*','*Light*','*ORG*','*org*','*save*','*EA*') -Property Name,LastWriteTime   
    # wenn es Unterschiede gibt ...
    if ($diff){
        "$share hat unterschiedliche Dateien"  
        $diff | ft -AutoSize
        Send-MailMessage –To "Email@.com" `  
                   –Subject ("ACHTUNG DATEI $diff UNTERSCHIEDLICH!")`  
                   –Body ("Die Datei $diff ist auf $share unterschiedlich")`  
                   –SmtpServer "smtp.com" `  
                   –From "noreplay@doamin.com" `  
                   -encoding ([System.Text.Encoding]::UTF8)    
    }
}
Doskias
Doskias 29.06.2021 um 14:51:08 Uhr
Goto Top
Moin,

wenn ich deinen Code lese (Zeile 3), dann sollte $diff.name den Dateinamen enthalten.

Gruß
Doskias
sugram
sugram 29.06.2021 um 15:10:13 Uhr
Goto Top
Hallo

Leider ist dem nicht so.

wenn ich dann das in $diff.name ändere erhelte ich die Email mit dem Inhalt
Die Datei  .name ist auf \\Sharename2\xyz\123 unterschiedlich
Doskias
Doskias 29.06.2021 um 15:26:48 Uhr
Goto Top
Zitat von @sugram:
Hallo
Leider ist dem nicht so.
wenn ich dann das in $diff.name ändere erhelte ich die Email mit dem Inhalt
> Die Datei  .name ist auf \\Sharename2\xyz\123 unterschiedlich
> 

Und wie sieht dein Ergebnis von $Diff aus? Sorry, aber wenn du Hilfe möchtest, dann liefere doch auch mal ein paar Infos. Ich habe keine Lust/Zeit deine Lösung hier nachzubauen, weil dafür werde ich nicht bezahlt face-smile

Setz zum Beispiel zum Testen mal ein
$diff
pause
vor dein send-MailMessage. Schau dir das Ergebnis an (poste es vielleicht hier, falls du Hilfe benötigst). Ich kenne deine Verzeichnisse ja auch nicht. vielleicht ist im $diff mehr als eine Datei, dann ergibt die Abfrage keinen Sinn und du müsstest mit $diff[x] noch die einzelnen Zeilen abfragen.

Gruß
Doskias
colinardo
Lösung colinardo 29.06.2021 aktualisiert um 15:51:04 Uhr
Goto Top
Zitat von @sugram:
Aber das mit den Dateinamen bekomme ich nicht hin?!

Die sind doch schon jeweils in der Variablen $diff gespeichert face-smile.

Wenn ich mir nun dafür eine Email senden lasse, erhalte ich zwar den UNC Pfad, aber nicht den Dateinamen
$diff ist ein Object mit einem oder mehreren Objekten die Eigenschaften haben, ergo musst du dies ja erst na auswählen!
Und da es mehrere Dateien sein können musst du die auch entsprechend formatieren
write-host "Folgende Dateien sind unterschiedlich:`n$($diff.Name -join "`r`n")"  

Zitat von @sugram:

Hallo

Leider ist dem nicht so.

wenn ich dann das in $diff.name ändere erhelte ich die Email mit dem Inhalt
> Die Datei  .name ist auf \\Sharename2\xyz\123 unterschiedlich
> 
Doch aber man muss Properties innerhalb von Anführungszeichen mit eine Subexpression ansprechen
"$($diff.Name) ist unterschiedlich"
sugram
sugram 29.06.2021 um 15:57:16 Uhr
Goto Top
Hallo

Man, da mus ich noch jede Menge lernen ...

Zitat von @colinardo:
Doch aber man muss Properties innerhalb von Anführungszeichen mit eine Subexpression ansprechen
> "$($diff.Name) ist unterschiedlich"
> 

Das war die Lösung.

Ich bedanke mich bei euch allen!
Doskias
Doskias 29.06.2021 aktualisiert um 16:05:57 Uhr
Goto Top
Zitat von @sugram:

Hallo

Man, da muss ich noch jede Menge lernen ...
Mussten und müssen wir alle (naja, nicht alle) noch. Schau am Besten hier:

Powershell Leitfaden für Anfänger
sugram
sugram 19.07.2021 um 09:52:48 Uhr
Goto Top
So, jetzt muss ich hier noch einmal fragen, da ich hier einfach nicht mehr weiterkomme.

Bei der Lösung ist es ja nun so, daß ich mehrere Emails bekomme. Nun wollte ich nur eine Email mit dem gesamten Inhalt.
Ich habe das ganze über die Clipboard Methode versucht zu lösen, aber das wird dann extrem unübersichtlich.
Daher dachte ich ich könnte das dann mit replace abändern, aber ich scheitere daran das sinnvoll zu lösen.

$ref_dir = '\\PC1\Share\123\xyz'  
$filefilter = '*.pvx'  
$shares = "\\PC2\Share\123\xyz","\\PC3\Share\123\xyz","\\PC4\Share\123\xyz"  
$ref = ls "$ref_dir\*" -File -Filter $filefilter -exclude '*Cali*','*Light*','*ORG*','*org*','*save*','*EA*','*TEST*'  
set-Clipboard -Value $null
foreach ($share in $shares){
    $diff = compare @($ref) @(ls "$share\*" -File -Filter $filefilter -exclude '*Cali*','*Light*','*ORG*','*org*','*save*','*EA*','*TEST*') -Property Name,LastWriteTime   
    if ($diff){
        $diff | ft -AutoSize
        Set-Clipboard -Value $share -Append
        Set-Clipboard -Value "<br />" -Append  
        Set-Clipboard -Value $diff -Append
        Set-Clipboard -Value "<br />" -Append  
    }
} 
$Ausgabe = Get-Clipboard


Send-MailMessage –To "Email@xyz.com" `  
                   –Subject ("ACHTUNG PVX DATEI UNTERSCHIEDLICH!")`  
                   –BodyAsHtml ("Die Datei <br /> $Ausgabe <br /> ist unterschiedlich")`  
                   –SmtpServer "smtp.com" `  
                   –From "noreplay@domain.com" `  
                   -encoding ([System.Text.Encoding]::UTF8) 

Daraus ergibt sich dann folgender Inhalt:

Die Datei 
\\PC2\Share\123\xyz @{Name=DATEI.pvx; LastWriteTime=03/09/2021 08:22:06; SideIndicator==>} @{Name=DATEI.pvx; LastWriteTime=03/09/1900 00:00:01; SideIndicator=<=} 
\\PC3\Share\123\xyz @{Name=DATEI.pvx; LastWriteTime=03/09/2021 08:22:06; SideIndicator==>} @{Name=DATEI.pvx; LastWriteTime=03/09/1900 00:00:01; SideIndicator=<=} 
\\PC4\Share\123\xyz @{Name=DATEI.pvx; LastWriteTime=03/09/2021 08:22:06; SideIndicator==>} @{Name=DATEI.pvx; LastWriteTime=03/09/1900 00:00:01; SideIndicator=<=} 
ist unterschiedlich 

Ziel wäre es das es in etwa so aussieht

Die Datei 
\\PC2\Share\123\xyz 
DATEI.pvx; LastWriteTime=03/09/2021 08:22:06; 
DATEI.pvx; LastWriteTime=03/09/1900 00:00:01
\\PC3\Share\123\xyz 
DATEI.pvx; LastWriteTime=03/09/2021 08:22:06; 
DATEI.pvx; LastWriteTime=03/09/1900 00:00:01;  
\\PC4\Share\123\xyz 
DATEI.pvx; LastWriteTime=03/09/2021 08:22:06; 
DATEI.pvx; LastWriteTime=03/09/1900 00:00:01;

ist unterschiedlich 

Ich habe gelesen das man das mit Replace abändern kann, aber meine Versuche alle Informationen wieder zu bekommen, schlugen bisher fehl.
Um ehrlich zu sein, steige ich da auch nicht ganz durch wie das funktioniert.

Evtl. könnte mir hier jemand noch einen tipp geben.