Ordner auf Änderungen prüfen?
Hallo,
ich möchte ein Powershell Skript schreiben, welches beim Ausführen jeden Ordner in einer Liste auf Änderungen seit dem letzten ausführen überprüft.
Im Internet finde ich nur Ergebnisse mit einem Script das dauerhaft im loop mit "$FileSystemWatcher".
Mein Ansatz wäre das ich für jeden Ordner der Liste einen Hash erstelle und in einer Datei zwischenspeichere, und diesen Wert beim nächsten mal mit dem neuen Vergleiche.
Wäre dieser Ansatz richtig und wie würde sich der gut realisieren lassen?
Vielen Dank für die Hilfe.
1 Antwort
für jeden Ordner der Liste einen Hash erstelle
...Eine prächtige Idee! 👍
Manchmal sieht man den Wald vor lauter Bäumen nicht. Um ehrlich zu sein, so weit hätte ich nicht mal gedacht.
und Natürlich lässt sich das realisieren sogar recht einfach:
#region FunctionDefine
function Get-FolderHash {
Param(
[Parameter(ValueFromPipeline=$true,Mandatory=$true)][string]$Path
)
#für das Einbeziehen von Unterverzeichnissen den Parameter -Recurse in die folgende Zeile einfügen.
$FolderString =(Get-ChildItem $Path -File -Force -ErrorAction SilentlyContinue |
Select-Object -Property Name,LastWriteTime,Length,Mode|
ConvertTo-Csv -NoTypeInformation| #mache aus der Objektliste ein CSV
Select-Object -Skip 1) -Join ';' #entferne den Header und vereinige alle Zeilen zu einen einzigen String
Write-Host $FolderString -fo yellow #Debug: den MörderString mal anzeigen
#erzeuge einen SHA512-Hash des erzeugten Strings
$hasher = [System.Security.Cryptography.HashAlgorithm]::Create('sha512')
$hash = $hasher.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($FolderString))
$hashString = [System.BitConverter]::ToString($hash)
$hashString.Replace('-', '')
}
#endregion
$FolderList= @(
'c:\windows\system32',
"$env:UserProfile\Documents",
"$env:UserProfile\Downloads",
"$env:UserProfile\Desktop\testfolder"
)
$HashFile='FolderHashes.csv'
if (!(Test-Path $HashFile)){
#wenn noch keine gespeicherten Werte existieren:
$HashList=$FolderList|
ForEach-Object {
$Hash=Get-FolderHash $_
[PSCustomObject]@{
Path = $_
Hash = $Hash
}
}
}
else {
#vergleiche gespeicherte Hashes mit aktuellen
$HashList=Import-Csv -Path $HashFile
$HashList=$HashList|
ForEach-Object {
$NewHash=Get-FolderHash $_.Path
#Debug: mal gucken
Write-Host $_.Path :
Write-Host alt: $_.Hash -fo green
Write-Host neu: $NewHash -fo red
if ($NewHash -eq $_.Hash){
$HasChanged=$False
}
else {
$HasChanged=$True
}
#diesmal den Objekten mitgeben ob sie sich verändert haben (HasChanged)
[PSCustomObject]@{
Path = $_.Path
Hash = $NewHash
HasChanged = $HasChanged
}
}
}
#mal alle anzeigen
$HashList|ft
#nur Ordner die sich verändet haben verarbeiten
$HashList|
Where-Object{$_.HasChanged}|
ForEach-Object {
#was immer geschehen soll (hier nur Meldung)
Write-Host Der Ordner : $_.Path wurde veraendert -fo red
}
#Hashes als csv speichern
$HashList|
Select-Object -Property Path,Hash | #wir brauchen HasChanged nicht speichern, also abwählen
Export-Csv -Path $HashFile -NoTypeInformation
pause
Das Script arbeitet beim ersten "Lauf" mit der FolderListe .
Existiert "FolderHashes.csv" wird die Folderliste ignoriert und es werden die im CSV gespeicherten Pfade verglichen. (dh. "FolderHashes.csv" löschen, wenn du die Folderlist änderst!)
Zum Hashen nutze ich hier "SHA512", Warsheinlich würde auch ein "schmalerer" Hashalgorithmus wie "MD5" oder "SHA1" ausreichen. ...aber was soll der Geiz...
in der vorliegenden Form werden nur die Dateien im angegebenen Ordner gehasht. Um unterordner einzubeziehen muss:
Get-ChildItem $Path -File -Force -ErrorAction SilentlyContinue
...zu :
Get-ChildItem $Path -File -Recurse -Force -ErrorAction SilentlyContinue
... geändert werden.
Erschrecke nicht beim Ausführen, ich habe ein paar Debug-Ausgaben eingebaut, damit du mal einen Einblick bekommst wie etwaige Zwischenergebnisse aussehen. (sind mit #Debug:... markiert)
Die zu hashenden yellow-Strings können ziemlich Fett werden 😮
das Verzeichnis in welchem du die HashDatei speichers sollte natürluch nicht verlichen werden, die wäre immer anders. (könnte man mit einem -Exclude auf den Dateinamen lösen, da hatte ich aber keine Lust mehr.
Du sollst ja auch noch was zu tun haben...😅
Vielen Dank für die umfangreiche und sehr hilfreiche Antwort.
Ich werde das Script durchlesen und schauen das ich alles verstehe und werde.
Danke für deine investierte Zeit. :)