Powershell Dateien archivieren und im LogSpeichern
Hallo zusammen,
bei uns werden auf einem Fileserver automatisch Ergebnisse der Produktion in verschiedenen Files abgelegt. Die entsprechenden Verzeichnisse platzen langsam aus allen nähten und ich habe versucht mit robocopy alle Dateien die älter als 30 Tage sind wegzusichern in ein Archivordner. Allerdings archiviert mir der Robocopy Job auch Ordner die nicht genutzt werden, was bei Maschinenreparaturen durchaus mal vorkommt. Gab jetzt schon mehrfach Probleme. Jetzt wollte ich es eleganter über die Powershell lösen und habe mir folgendes Script zusammen gesucht
Jetzt habe ich das Problem das ganze in ein Log zu bekommen. Mit Out-file bekomme ich immer Fehlermeldungen wenn ich $logfile angebe, genauso wenn ich mit > $logfile arbeite.
Ich komme gerade nicht weiter, ich möchte nur eine Datei haben, wo ich nachvollziehen kann, wann er welche Dateien verschoben hat.
bei uns werden auf einem Fileserver automatisch Ergebnisse der Produktion in verschiedenen Files abgelegt. Die entsprechenden Verzeichnisse platzen langsam aus allen nähten und ich habe versucht mit robocopy alle Dateien die älter als 30 Tage sind wegzusichern in ein Archivordner. Allerdings archiviert mir der Robocopy Job auch Ordner die nicht genutzt werden, was bei Maschinenreparaturen durchaus mal vorkommt. Gab jetzt schon mehrfach Probleme. Jetzt wollte ich es eleganter über die Powershell lösen und habe mir folgendes Script zusammen gesucht
$path = "C:\Temp"
$date = get-date -format "yyyy-MM-dd-HH-mm"
$file = ("Log_" + $date + ".log")
$logfile = $path + "\" + $file
$sourceRoot = 'C:\Users\XX\Downloads'
$targetRoot = 'C:\Users\XX\Desktop\Test'
gci $sourceRoot -Recurse | ?{!$_.PSIsContainer -and $_.LastWriteTime -lt (Get-Date).AddDays(-1)} | %{
# Name des neuen Ordners erstellen indem der Quell-Root durch den Zielroot ersetzt wird
$newDir = $_.DirectoryName.Replace($sourceRoot,$targetRoot)
# Zielordnerstruktur erstellen
new-item -ItemType Directory -Path $newDir -Force
# File an seinen neuen Ort verschieben
move-item $_.FullName -Destination "$newDir\$($_.Name)" -Force
}
Jetzt habe ich das Problem das ganze in ein Log zu bekommen. Mit Out-file bekomme ich immer Fehlermeldungen wenn ich $logfile angebe, genauso wenn ich mit > $logfile arbeite.
Ich komme gerade nicht weiter, ich möchte nur eine Datei haben, wo ich nachvollziehen kann, wann er welche Dateien verschoben hat.
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 583215
Url: https://administrator.de/contentid/583215
Ausgedruckt am: 22.11.2024 um 16:11 Uhr
15 Kommentare
Neuester Kommentar
Moin,
move-item hat bei erfolgreicher Ausführung keine Ausgabe, diese musst du dir also selbst basteln.
Z.B.:
Gruß Thomas
PS: Bitte zukünftig auf die richtige Forenkategorie (in diesem Fall "Batch & Shell") achten.
move-item hat bei erfolgreicher Ausführung keine Ausgabe, diese musst du dir also selbst basteln.
Z.B.:
$logfile="C:\Temp\Log_$((get-date).ToString('yyyy-MM-dd-HH-mm')).log"
$sourceRoot = 'C:\Users\XX\Downloads'
$targetRoot = 'C:\Users\XX\Desktop\Test'
gci $sourceRoot -Recurse | ?{!$_.PSIsContainer -and $_.LastWriteTime -lt (Get-Date).AddDays(-1)} | %{
# Name des neuen Ordners erstellen indem der Quell-Root durch den Zielroot ersetzt wird
$newDir = $_.DirectoryName.Replace($sourceRoot,$targetRoot)
# Zielordnerstruktur erstellen
new-item -ItemType Directory -Path $newDir -Force
# File an seinen neuen Ort verschieben
move-item $_.FullName -Destination "$newDir\$($_.Name)" -Force -EA SilentlyContinue
# Prüfen, ob das Verschieben erfolgreich war
if ($?) {(get-date).ToString('dd.MM.yyyy HH:mm')+" - '$_' verschoben nach '$newdir'" | Out-File -Append $logfile }
else {(get-date).ToString('dd.MM.yyyy HH:mm')+" - Fehler beim Verschieben von '$_' nach '$newdir'" | Out-File -Append $logfile }
}
Gruß Thomas
PS: Bitte zukünftig auf die richtige Forenkategorie (in diesem Fall "Batch & Shell") achten.
Zitat von @SlainteMhath:
Zeile 10+11: können ersatzlos gestrichen werden (was versuchst du da zu tun??)
Den Zielordner bestimmen. Das ist schon OK so, wenn man jede Datei einzeln verschiebt.Zeile 10+11: können ersatzlos gestrichen werden (was versuchst du da zu tun??)
Wobei man das auch gleich mit .FullName machen könnte.
Hm, naja, nachdem nur Einträge verarbeitet werden, die KEINE Verzeichnisse sind, führt ein
Doch immer dazu das $newDir = $targetroot ist, oder nicht?
Und dann wird $_.FullName nach "$newDir\$($_.Name)" verschoben. Würde als Destination auch $targetroot + $_.Name ausreichen
Recht verworrener Code :D
$newDir = $_.DirectoryName.Replace($sourceRoot,$targetRoot)
Und dann wird $_.FullName nach "$newDir\$($_.Name)" verschoben. Würde als Destination auch $targetroot + $_.Name ausreichen
Recht verworrener Code :D
Zitat von @SlainteMhath:
Hm, naja, nachdem nur Einträge verarbeitet werden, die KEINE Verzeichnisse sind, führt ein
Doch immer dazu das $newDir = $targetroot ist, oder nicht?
Nein. Da er mit "-recurse" arbeitet wird $_.DirectoryName bei untergeordneten Verzeichnissen immer verschieden sein.Hm, naja, nachdem nur Einträge verarbeitet werden, die KEINE Verzeichnisse sind, führt ein
Doch immer dazu das $newDir = $targetroot ist, oder nicht?
Moin,
gruselig formatiert und wenig perfomant und unflexibel das Ganze.
Das macht, was Du willst.
hth
Erik
gruselig formatiert und wenig perfomant und unflexibel das Ganze.
PARAM(
$logpath = "C:\Temp\",
$file_prefix = "log_",
$sourceRoot = 'C:\Users\XX\Downloads',
$targetRoot = 'C:\Users\XX\Desktop\Test'
)
$logfile = $logpath + $file_prefix + $(get-date -format "yyyy-MM-dd-HH-mm") + ".log"
if(-not (test-path $targetRoot)) {
out-file -InputObject "Abbruch! $targetRoot existiert nicht!" -FilePath $logfile -Append -Encoding utf8
Write-error "Das Skript wurde abgebrochen. Der Zielpfad existiert nicht."
exit 1
}
$files = get-childitem $sourceRoot -Recurse | ?{!$_.PSIsContainer -and $_.LastWriteTime -lt (Get-Date).AddDays(-1)}
foreach ($file in $files) {
# Name des neuen Ordners erstellen indem der Quell-Root durch den Zielroot ersetzt wird
$newDir = $file.DirectoryName
$newDir = $newDir.Replace("$sourceRoot","$targetRoot")
# Zielordnerstruktur erstellen
if(-not (test-path $newDir)) {
new-item -ItemType Directory -Path $newDir
}
# File an seinen neuen Ort verschieben
try {
move-item $file.FullName -Destination "$newDir\$($file.Name)" -Force
Out-File -InputObject "$file.fullname wurde nach $newDir verschoben." -FilePath $logfile -Append -Encoding utf8
}
catch {
Out-File -InputObject "FEHLER! $file.fullname wurde NICHT nach $newDir verschoben." -FilePath $logfile -Append -Encoding utf8
}
}
Das macht, was Du willst.
hth
Erik
Zitat von @HAinsane:
Welche Möglichkeiten gibt es dann mit einer Ausgabe zu arbeiten oder wie bastelt man sich eine Ausgabe?
Ich hab doch oben ein Beispiel mit einer Ausgabe gepostet.Welche Möglichkeiten gibt es dann mit einer Ausgabe zu arbeiten oder wie bastelt man sich eine Ausgabe?
Zitat von @TK1987:
Ein weiteres Beispiel wie man sowas strukturiert z.B. in eine CSV schreibt, hier nur mal ein Ausschnitt um @erikro 's try catch Variante aufzugreifenZitat von @HAinsane:
Welche Möglichkeiten gibt es dann mit einer Ausgabe zu arbeiten oder wie bastelt man sich eine Ausgabe?
Ich hab doch oben ein Beispiel mit einer Ausgabe gepostet.Welche Möglichkeiten gibt es dann mit einer Ausgabe zu arbeiten oder wie bastelt man sich eine Ausgabe?
$log = @()
# .........
try {
move-item $file.FullName -Destination "$newDir\$($file.Name)" -Force -EA Stop
$log += [pscustomobject]@{Date=(get-date);File=$file.Fullname; Status="OK"}
}catch {
$log += [pscustomobject]@{Date=(get-date);File=$file.Fullname; Status=$_.Exception.Message}
}
# .....
# und am Ende dann ausgeben
$log | export-csv $logfile -NoType -Delimiter ";" -Encoding UTF8
Oder man loggt sämtliche Infos der Konsole, mit Start-Transcript mit.
Möglichkeiten gibt es ja viele.
https://www.msxfaq.de/code/powershell/pserrhandling.htm
https://www.windowspro.de/script/fehlerbehandlung-powershell-erroraction ...
Moin,
Jo. Da hast Du recht. Ich würde es aber nach jedem Schleifendurchlauf ins Log schreiben. Sonst besteht die Gefahr, dass man kein Log hat, falls das Skript unerwartet abbricht.
Liebe Grüße
Erik
Zitat von @144705:
So landet dann auch etwas mehr Info zum Fehler im Log und die Weiterverarbeitung ist leichter.
> $log = @()
>
> # .........
>
> try {
> move-item $file.FullName -Destination "$newDir\$($file.Name)" -Force -EA Stop
> $log += [pscustomobject]@{Date=(get-date);File=$file.Fullname; Status="OK"}
> }catch {
> $log += [pscustomobject]@{Date=(get-date);File=$file.Fullname; Status=$_.Exception.Message}
> }
>
> # .....
> # und am Ende dann ausgeben
> $log | export-csv $logfile -NoType -Delimiter ";" -Encoding UTF8
>
Jo. Da hast Du recht. Ich würde es aber nach jedem Schleifendurchlauf ins Log schreiben. Sonst besteht die Gefahr, dass man kein Log hat, falls das Skript unerwartet abbricht.
Liebe Grüße
Erik
Dann hast du den Parameter -EA Stop oder ausgeschrieben -ErrorAction Stop beim Move-Item Command nicht eingesetzt.