petere
Goto Top

Dateien Löschen als Dienst mit Filterung

Hallo,

ich suche ein Tool, welches auf einem Windows-Server läuft und folgendes kann:

- Man gibt mehrere Verzeichnisse an
- Filter nach Dateiname und Dateialter
z.B. Lösche alle Dateien und leere Unterverzeichnisse, die älter als 90 Tage sind, mit *.bak enden ABER nicht die, welche am ersten jeden Monats erstellt wurden.

Habt ihr da ein Tool, was das kann?
Viele Grüße,
Peter

Content-Key: 236000

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

Printed on: April 24, 2024 at 23:04 o'clock

Member: jsysde
jsysde Apr 19, 2014 at 07:47:29 (UTC)
Goto Top
Moin.

Spontan fällt mir da DelAge32 ein:
http://www.horstmuc.de/wbat32d.htm

Cheers,
jsysde
Member: petere
petere Apr 19, 2014 at 08:08:14 (UTC)
Goto Top
Oh das klingt toll.
Jetzt ist die frage: verzichte ich auf den Filter, dass Dateien des Monatsersten nicht gelöscht werden oder gibt's einen workaround.

Mit fällt spontan nix ein.
Member: jsysde
jsysde Apr 19, 2014 at 08:17:19 (UTC)
Goto Top
Moin.

Auch wieder spontan: Nach Datum filtern innerhalb der Batchdatei, mit der du DelAge32.exe aufrufst und dann eben DelAge32.exe mehrmals aus der Batch heraus starten mit unterschiedlichen Parametern, also einmal "Files von <aktuelles Datum> bis <aktuelles Datum -n Tage>", dann "letzter Monat exclude 01.Tag des Monats" usw. Ist sicherlich ein bisschen Gebastel und Geskripte, aber es funktioniert.

Cheers,
jsysde
Member: bastla
bastla Apr 19, 2014 updated at 09:38:20 (UTC)
Goto Top
Hallo petere!

Ein VBScript für diesen Zweck könnte etwa so aussehen:
' * hier eigenen Bedürfnissen anpassen *  
Ordnerliste =    "D:\Ordnerliste.txt" 'Liste der zu bearbeitenden Ordner; 1 Ordner je Zeile  
Dateitypen =     "D:\Typen.txt" 'Liste der Dateitype; 1 Typ je Zeile  
Alter =          90 'Alter der zu löschenden Dateien in Tagen  
ErstellungsTag = 1 'Dateien, die an diesem Tag des Monats erstellt wurden, nicht löschen  
' * Ende der Anpassungen *  


Set fso = CreateObject("Scripting.FileSystemObject")  
Verzeichnis = Split(fso.OpenTextFile(Ordnerliste).ReadAll, vbCrLF) 'Ordnerliste einlesen  
Include = LCase("#" & Replace(fso.OpenTextFile(Dateitypen).ReadAll, vbCrLF, "#") & "#") 'Dateitypen einlesen  

Heute = Date()

For n = 0 To UBound(Verzeichnis) 'alle Ordner durchgehen  
    Set Ordner = fso.GetFolder(Verzeichnis(n))
    DeleteInFolder(Ordner) 'Lösch-Unterprogramm für Ordner aufrufen  
Next

Sub DeleteInFolder(Ordner)
Set Dateien = Ordner.Files
For Each Datei In Dateien 'alle Dateien in diesem Ordner durchgehen  
    If Datei.DateLastModified < (Heute - Alter) Then 'Datei ist alt genug  
        If InStr(Include, "#" & LCase(fso.GetExtensionName(Datei.Name)) & "#") > 0 Then 'Datei hat passenden Typ  
            If Day(Datei.DateCreated) <> ErstellungsTag Then 'nicht am festgelegten Tag eines Monats erstellt  
                On Error Resume Next
                'Datei.Delete 'Datei löschen  
                WScript.Echo Datei.DateLastModified & "_" & Datei.Path 'zu löschende Datei nur anzeigen  
                'Falls Fehler "permission denied" aufgetreten, ignorieren, ansonsten Script abbrechen  
                If Err And Err <> 70 Then MsgBox "Fehler (Code=" & Err & ")", vbCritical: WScript.Quit  
                On Error Goto 0
            End If
        End If
    End If
Next

For Each Unter In Ordner.SubFolders 'alle Unterordner durchgehen  
    DeleteInFolder(Unter) 'DeleteInFolder rekursiv aufrufen  
    If (Unter.SubFolders.Count + Unter.Files.Count) = 0 Then 'Unterverzeichnis leer  
        'If Unter.DateLastModified < (Heute - Alter) Then Unter.Delete 'löschen, wenn Ordner alt genug  
        If Unter.DateLastModified < (Heute - Alter) Then WScript.Echo "#" & Unter.DateLastModified & "_" & Unter.Path 'zu löschenden Ordner nur anzeigen  
    End If
Next
End Sub
Benötigt werden die in den Zeilen 2 und 3 angeführten Textdateien, um die zu bearbeitenden Verzeichnisse bzw die zu berücksichtigenden Dateitypen festzulegen - für die Dateitypen könnte die Datei zB folgenden Inhalt haben:
bak
tmp
log
- damit würden dann nur "*.bak"-, "*.tmp"- und "*.log"-Dateien gelöscht. Ein Filter für Dateinamen ist derzeit noch nicht integriert, ließe sich aber bei Bedarf "nachrüsten".

Zum Testen das Script mit
cscript "D:\Scriptname.vbs"
aus einer CMD-Shell starten - es werden dann alle Dateien und Ordner (Kennzeichnung mit vorangestelltem "#") angezeigt, die gelöscht würden, mit Änderungsdatum und Pfad angezeigt. Ordner werden allerdings nur aufscheinen, wenn sie bereits vorher leer waren (da ja noch keine Dateien gelöscht werden).

Wenn das Ergebnis ok aussieht, die Zeilen 27 und 40 aktivieren (indem der Apostroph ' am Zeilenanfang entfernt wird) und vor die (dann nicht mehr benötigten) Zeilen 28 und 41 einen Apostroph setzen oder diese Zeilen einfach entfernen. Dann kann das Script auch ohne "cscript" bzw per Doppelklick gestartet werden.

Noch ein Hinweis: Bei Verzeichnissen wird nur das Alter, aber nicht der Erstellungstag, geprüft - ein leeres Verzeichnis zu behalten, weil es am 1. eines Monats erstellt wurde, dürfte nicht nötig sein, wobei sich aber natürlich auch diese Prüfung ergänzen ließe.

Grüße
bastla
Member: petere
petere Apr 19, 2014 at 09:33:02 (UTC)
Goto Top
Danke euch beiden, das sind echt sehr gute loesungen.
Member: bastla
bastla Apr 19, 2014 at 09:33:51 (UTC)
Goto Top
@ jsysde
Im Fall des Falles würde ich eher "delage32" mit "/preview" aufrufen und dann jede der aufgelisteten Dateien auf den Erstellungstag prüfen - das Löschen der danach leeren Ordner bliebe so allerdings auf der Strecke ...

Grüße
bastla
Member: colinardo
Solution colinardo Apr 19, 2014 updated at 11:10:37 (UTC)
Goto Top
Hallo Peter,
und hier noch die Powershell-Variante:
function Cleanup-Folders {
    param(
        [parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string[]]$folders,
        [int]$olderthandays,
        [string]$filepattern = "*.*",  
        [switch]$RemoveEmptyDirs,
        [switch]$Recurse,
        [ValidateRange(1,31)][int]$keepfileswithdayofmonth,
        [string]$logfile
    )

    process{
        
        foreach($folder in $folders){
            if (Test-Path $folder) {
                # process files -----------
                if ($Recurse){
                    $files = gci $folder -Recurse | ?{!$_.PSIsContainer}
                }else{
                    $files = gci $folder | ?{!$_.PSIsContainer}
                }
                if ($olderthandays -gt 0){
                    $files = $files | ?{$_.Name -like $filepattern -and $_.LastWriteTime -lt (get-date).AddDays(-$olderthandays)} 
                }
                if ($keepfileswithdayofmonth -gt 0){
                    $files = $files | ?{(get-date $_.LastWriteTime).Day -ne $keepfileswithdayofmonth}
                }
                $files = $files | ?{$_.Name -like $filepattern}
                foreach($file in $files){
                    remove-item $file.FullName -Force -EA SilentlyContinue -EV err
                    if ($err.Count -gt 0){
                        write-host "Beim Löschen von Ordner: '$($file.Fullname)' ist ein Fehler aufgetreten: $($err.ErrorDetails.Message)" -BackgroundColor Red -ForegroundColor Yellow  
                        if ($logfile){echo "ACHTUNG Fehler: $($err.ErrorDetails.Message)" | out-file $logfile -Force -Append}  
                    }else{
                        write-host "Lösche Datei: '$($file.Fullname)'" -ForegroundColor Green  
                        if($logfile){echo "$(get-date -Format "dd.MM.yyyy hh:mm:ss") - Datei gelöscht: $($file.FullName)" | out-file $logfile -Force -Append}  
                    }
                }
                
                # process empty folders ----
                if($RemoveEmptyDirs){
                    if ($Recurse){
                        $allSubfolders = gci $folder -Recurse | ?{$_.PSIsContainer}
                    }else{
                        $allSubfolders = gci $folder | ?{$_.PSIsContainer}
                    }
                    $allSubfolders = $allSubfolders | ?{$_.GetDirectories().Count -eq 0 -and $_.GetFiles().Count -eq 0}
                    foreach($f in $allSubfolders){
                        remove-item $f.FullName -Force -EA SilentlyContinue -EV err
                        if ($err.Count -gt 0){
                            write-host "Beim Löschen von Ordner: '$($f.Fullname)' ist ein Fehler aufgetreten: $($err.ErrorDetails.Message)" -BackgroundColor Red -ForegroundColor Yellow  
                            if ($logfile){echo "ACHTUNG Fehler: $($err.ErrorDetails.Message)" | out-file $logfile -Force -Append}  
                        }else{
                            write-host "Lösche Ordner: '$($f.Fullname)'" -ForegroundColor Green  
                            if($logfile){echo "$(get-date -Format "dd.MM.yyyy hh:mm:ss") - Leerer Ordner gelöscht: $($f.FullName)" | out-file $logfile -Force -Append}  
                        }
                    } 
                } 
            }
        }
    }
}
Der Aufruf der Function erfolgt dann so:
Cleanup-Folders -folders "C:\ordner1","d:\Ordner2","E:\ordner3" -olderthandays 90 -filepattern "*.bak" -Recurse -RemoveEmptyDirs -keepfileswithdayofmonth 1 -logfile "C:\logfile.txt"
Der Parameter -folders ist dabei Pflichtangabe und es können mehrere Ordner mit Komma getrennt angegeben werden, die anderen Parameter sind Optional und können nach Bedarf kombiniert werden. Wird kein -filepattern angegeben wird von *.* ausgegangen.

Viel Spaß face-smile

Grüße Uwe
Member: petere
petere Apr 19, 2014 at 11:10:52 (UTC)
Goto Top
Super, herzlichen Dank