easy4breezy
Goto Top

Powershell Old Files and Folders Deletion after x days

Hallo face-smile

Auf einem meiner Laufwerke möchte ich alte Ordner und Dateien automatisiert löschen.
Die Verzeichnisstruktur ist folgende:

Laufwerk
AbteilungA
@scan
Folder123
bild.jpg
AbteilungB
@scan
Folderabc
beispiel.pdf
AbteilungC
@scan
Folderxyz
text.txt

AbteilungA soll komplett unangetastet bleiben.
Die @scan Folder sollen erhalten bleiben, alles was sich darin befindet kann gelöscht werden.
Ordner und Dateien in den anderen Abteilungen sollen nach 28 Tagen ohne Access gelöscht werden.

Das Problem ist aber, dass wenn ich in einem Unterordner einen weiteren Ordner habe und dort eine Datei hineinkopiere, wird die Access Time nur von dem Ordner geändert, in dem die Datei selber ist.
Dann versucht das Skript aber den ganzen Ordner mit allen Unterordnern zu löschen, da es von oben nach unten geht.
Ich müsste aber von unten anfangen.

Vielleicht kann mir jemand behilflich sein face-smile

$root = "C:\Users\Userxyz\Test"  
$abteilunga = "*\AbteilungA\*"  
$scan = "*\@scan\*"  
$date = (Get-Date).AddDays(-28)
$folders = Get-ChildItem $root -recurse | ForEach-Object {Get-ChildItem $_.FullName} | Where-Object {$_.Name -notlike $abteilunga}

foreach($folder in $folders){
    $folder | Where-Object {($_.LastAccessTime -lt $date) -and ($_.PSIsContainer -eq $True) -and ($_.Name -notlike $scan)} | Remove-Item
    $folder| Where-Object {($_.LastAccessTime -lt $date) -and ($_.PSIsContainer -ne $True)} | Remove-Item
}


Liebe Grüße!

Content-ID: 332457

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

Ausgedruckt am: 22.11.2024 um 16:11 Uhr

132692
132692 17.03.2017, aktualisiert am 18.03.2017 um 13:49:06 Uhr
Goto Top
Dann versucht das Skript aber den ganzen Ordner mit allen Unterordnern zu löschen, da es von oben nach unten geht.
Ich müsste aber von unten anfangen.
Sortiere sie einfach der Länge nach face-smile sort-object ist dein Freund.
Hier gibts auch noch was fertiges Dateien Löschen als Dienst mit Filterung

$root = "C:\Users\Userxyz\Test"   
$filtered = gci $folder -Recurse | ?{$_.Fullname -notlike "$folder\AbteilungA*" -and $_.LastAccessTime -lt (get-date).AddDays(-28)}  
# remove old files
$filtered | ?{!$_.PSIsContainer} | remove-item -force
# remove old empty folders
$filtered | ?{$_.PSISContainer -and $_.Name -ne '@scan' -and $_.GetFiles('*',[System.IO.SearchOption]::AllDirectories).Count -eq 0} | sort {$_.Fullname.Length} -Desc | remove-item -recurse -Force  

Gruß p.
easy4breezy
easy4breezy 20.03.2017 um 14:25:55 Uhr
Goto Top
Das fertige Skript hat mir schon mal geholfen, leider scheitert es immer noch an einer Kleinigkeit..
Abteilung A wird ignoriert, das passt schon mal.
Nur löscht es gar keine leeren Ordner mehr, egal ob alt oder neu..

$folder in Zeile 24 hat irgendwie auch keinen Inhalt mehr.

Vielleicht weißt du, bzw. jemand anders, woran es noch liegen könnte face-smile


function Cleanup-Folders{
    param(
        [string]$folders,
        [string]$logfile
    )

    process{
    $time = $_.LastAccessTime -lt (get-date).AddDays(-28)
        $filtered = gci $folders -Recurse | ?{$_.Fullname -notlike "$folders\AbteilungA*"}  
        foreach($folder in $filtered){
                # delete old files
                $files = gci $folder -Recurse | ?{!$_.PSIsContainer -and $time}
                foreach($file in $files){
                    remove-item $file.FullName -Force -EA SilentlyContinue -EV err 
                    if ($err.Count -gt 0){
                        write-host "Beim Löschen von Datei: '$($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}  
                    }
                
                # delete empty folders
                $allSubfolders = gci $folder -Recurse | ?{$_.PSISContainer -and $time -and $_.Name -notlike "$folders\*\@scan*"`  
                -and $_.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}  
                    }
                } 
            } 
        }
    }
}

Cleanup-Folders -folders "C:\Users\xyz\Documents\_Test" -logfile "C:\Users\xyz\Desktop\log_old.txt"  
132692
Lösung 132692 20.03.2017 aktualisiert um 16:21:18 Uhr
Goto Top
Wo hast du den Müll her? Das Skript von der verlinkten Seite sieht ganz anders aus!
und das
$time = $_.LastAccessTime -lt (get-date).AddDays(-28)
kann ja schon mal gar nicht funktionieren wenn du das Boolean-Ergebnis in einer Pipe verwendest ...

btw. s. mein Skript im letzten Kommentar da ist alles drin was du brauchst!!
easy4breezy
easy4breezy 29.03.2017 um 16:15:50 Uhr
Goto Top
Hier ist mein derzeitiger Stand.
Ich habe es um eine Logfile-Historie erweitert (dieses kann optional angegeben werden, ansonsten wird ein Default Pfad genommen).
Die Path Angabe ist Pflicht.

Mein Problem ist jetzt aber noch, dass in einem der Unterordner jemand einen eigenen Ordner mit @scan erstellt haben könnte.
Dieses wird dann nicht gelöscht, was aber der Fall sein soll.
Kann ich festlegen, dass @scan nur in $path\AbteilungB\ z.B. gelöscht werden soll?
$path\AbteilungB\Ordner\@scan soll dann gelöscht werden.

Und ein weiteres Problem ist, dass wenn z.B Abteilung B komplett leer wäre, auch gelöscht wird.


Vielleicht kannst du mir doch nochmal helfen.
Dein Skript hat mir zwar geholfen, aber es war nicht ganz wonach ich gesucht hatte.

function Log-Cleanup{
    param
    (
        $log,
        $fileextension
    )

    if(Test-Path $($log+$fileextension)){
        for($i=5; $i -gt 0; $i--){
            if(Test-Path $($log+"-"+$i+$fileextension)){  
                if($i -eq 5){
                    Remove-Item $("$log-$i$fileextension")  
                }else{
                    Rename-Item $("$log-$i$fileextension") $("$log-$($i+1)$fileextension")  
                }
            }
        }
        Rename-Item $("$log$fileextension") $("$log-1$fileextension")  
    }
}

function Delete-Item{
    param
    (
        $log
    )
    
    foreach($item in $delete){
        remove-item $item.FullName -Force -EA SilentlyContinue -EV err
        if ($err.Count -gt 0){
            Write-Host "Beim Löschen von: '$($item.Fullname)' ist ein Fehler aufgetreten: $($err.ErrorDetails.Message)" -BackgroundColor Red -ForegroundColor Yellow  
            echo "ACHTUNG Fehler;$($err.ErrorDetails.Message)" | Out-File $log -Force -Append  
        }else{
            Write-Host "Lösche '$($item.Fullname)'" -ForegroundColor Green  
            echo "$(Get-Date -Format "dd.MM.yyyy hh:mm:ss");$($item.FullName)" | Out-File $log -Force -Append  
        }
    } 
}

function Cleanup-Folders{
    param
    (
        [parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string[]]$path,
        $loglocation,
        $logname = "log-old",  
        $filepattern = ".txt"  
    )
    
    if($loglocation){
        $loglocation = $loglocation.TrimEnd("\")+"\"  
        $loglocationexists = Test-Path $loglocation
        if($loglocationexists -eq $false){
            Write-Host "Path not found: " $loglocation -BackgroundColor Red -ForegroundColor Yellow  
            Exit 1
        }
        Log-Cleanup -log $loglocation$logname -fileextension $filepattern
    }else{
        $loglocation = $pwd.ToString()+"\Documents\_log\"  
        $loglocationexists = Test-Path $loglocation
        if($loglocationexists -eq $false){
            New-Item -Path $($pwd.ToString()+"\Documents\") -Name "_log" -ItemType Directory  
        }
        Log-Cleanup -log $loglocation$logname -fileextension $filepattern
    }
    $logfile = $loglocation+$logname+$filepattern

    # fetch public drive
    $filtered = gci $path -Recurse | ?{$_.FullName -notlike "$path\AbteilungA*" -and $_.LastAccessTime -lt (Get-Date).AddDays(-28)}  
    foreach($folder in $filtered){

        # delete old files
        $delete = $folder | ?{!$_.PSIsContainer}
        Delete-Item -log $logfile

        # delete old and empty folders
        $delete = $folder | ?{$_.PSISContainer -and $_.Name -notlike "@scan*" -and $_.GetDirectories().Count -eq 0 -and $_.GetFiles().Count -eq 0}  
        Delete-Item -log $logfile
    }
}

Cleanup-Folders-path "C:\Users\xyz\Documents\Test" -loglocation "C:\Users\xyz\Documents\Test\log\"