none
Lösch Skript mit der Möglichkeit ganze Ordner zu exkludieren RRS feed

  • Frage

  • Hallo an Alle,

    ich hoffe ihr könnt mir helfen. Ich bin gerade daran mit Hilfe von Powershell Dateien zu löschen welche älter sind als X Tage. Das funktioniert auch alles wunderbar. Jetzt habe ich aber das Problem, dass ich gewisse Ordner exkludieren möchte. Das funktioniert aber leider nicht so wie ich möchte. Daher teile ich jetzt mal mit was ich bereits habe und hoffe das ihr mir helfen könnt.

    Ordner Struktur sieht Beispielhaft so aus:

    Mein Löschskript für die Dateien wo älter sind als X Tage sieht so aus:

    Quelle = "C:\Abteilungen\"
    $Days = 10
    $ext = "*.txt","*.log"
    $log = "$Source$(get-date -format yymmddHHmmss).txt
    $DateBeforeXDays = (Get-Date).AddDays(-$Days)
    
    Start-Transcript $log
    get-childitem $Source\* -include $ext -recurse | where {$_.lastwritetime -lt $DateBeforeXDays -and -not $_.psiscontainer} | % {remove-item $_.fullname -force -verbose -whatIf}
    Stop-Transcript

    Das Löschen der Dateien die älter sind als in dem Fall 10 Tage funktioniert prima nur leider möchte jetzt der Chef der Abteilung1 nicht das das bei ihm passiert und die Mitarbeiter bei Abteilung3 möchten es auch nicht.

    Wie kann ich also eine Auswahl mit einfließen lassen bzw diese Ordner oder sogar Unterordner exkludieren ?

    Für eure Hilfe wäre ich sehr dankbar.

      

    Mittwoch, 12. Februar 2020 12:47

Antworten

  • Seit Powershell Version 3 beherrscht Get-ChildItem den Parameter -File. Da sparst Du Dir das nachträgliche Filtern mit Where-Object.

    Die Abteilungsordner kannst Du mit einem -notmatch auf den kompletten Pfad rausfiltern.

    Get-ChildItem -Path $Source\* -Include $ext -Recurse -File | 
        Where-Object { $_.lastwritetime -lt $DateBeforeXDays -and $_.FullName -notmatch 'Abteilung1|Abteilung3' } | 
            ForEach-Object { Remove-Item $_.fullname -Force -Verbose -WhatIf }
    Davon unabhängig: Tu Dir selbst und allen anderen, die sich Deine Scripte ansehen, einen Gefallen und vermeide Aliasse und Abkürzungen in Scripts. Das macht das Lesen und Verstehen leichter.


    Live long and prosper!

    (79,108,97,102|%{[char]$_})-join''

    Mittwoch, 12. Februar 2020 13:43

Alle Antworten

  • Seit Powershell Version 3 beherrscht Get-ChildItem den Parameter -File. Da sparst Du Dir das nachträgliche Filtern mit Where-Object.

    Die Abteilungsordner kannst Du mit einem -notmatch auf den kompletten Pfad rausfiltern.

    Get-ChildItem -Path $Source\* -Include $ext -Recurse -File | 
        Where-Object { $_.lastwritetime -lt $DateBeforeXDays -and $_.FullName -notmatch 'Abteilung1|Abteilung3' } | 
            ForEach-Object { Remove-Item $_.fullname -Force -Verbose -WhatIf }
    Davon unabhängig: Tu Dir selbst und allen anderen, die sich Deine Scripte ansehen, einen Gefallen und vermeide Aliasse und Abkürzungen in Scripts. Das macht das Lesen und Verstehen leichter.


    Live long and prosper!

    (79,108,97,102|%{[char]$_})-join''

    Mittwoch, 12. Februar 2020 13:43
  • Hi,

    vielen Dank für die Hilfe und ich werde versuchen mich zu bessern mit der Ausformulierung.

    Gibt es noch die Möglichkeit, die Ausnahmen in eine Textdatei zu schreiben und von dort dann einlesen zu lassen bei "-notmatch" ?

    Also ich würde dann eine zentrale Datei führen in der die Ausnahmen definiert wären.

    Die Ausnahmen so wie Sie im Moment im Skript hinterlegt sind führen aber immer dazu das der komplette Ordner als Ausnahme gilt. Kann man das im Einzelfall auch auf Dateien herunterbrechen ?

    Montag, 24. Februar 2020 09:20
  • Hi,

    vielen Dank für die Hilfe und ich werde versuchen mich zu bessern mit der Ausformulierung.

    Gibt es noch die Möglichkeit, die Ausnahmen in eine Textdatei zu schreiben und von dort dann einlesen zu lassen bei "-notmatch" ?

    Also ich würde dann eine zentrale Datei führen in der die Ausnahmen definiert wären.

    Die Ausnahmen so wie Sie im Moment im Skript hinterlegt sind führen aber immer dazu das der komplette Ordner als Ausnahme gilt. Kann man das im Einzelfall auch auf Dateien herunterbrechen ?

    Vielleicht die Möglichkeit über eine Dateiausnahmeliste Dateien in die Ausnahme zu übernehmen und über eine Ordnerausnahmeliste Ordner in die Ausnahme zu übernehmen.
    Montag, 24. Februar 2020 09:38
  • - Zur Auslagerung würde ich dir eine CSV empfehlen. Damit ist das Verarbeiten des Inhalts leichter.

    - Ausnahmen kann man auch auf Dateiebene machen. Dann müsstest du aber vorher prüfen, ob der Ordner eine Ausnahmedatei enthält und wenn ja den ganzen Ordner exkludieren.  

    Gruß

    Montag, 24. Februar 2020 09:46
  • Gibt es noch die Möglichkeit, die Ausnahmen in eine Textdatei zu schreiben...

     ... führen aber immer dazu das der komplette Ordner als Ausnahme gilt. Kann man das im Einzelfall auch auf Dateien herunterbrechen ?

    Man kann alles beliebig komplex gestallten. Aber je komplexer ein System wird, desto fehleranfälliger wird es auch. Vielleicht kann man das ein oder andere Problem ja "administrativ" lösen (also im Sinne von "nicht technisch").

    Man könnte "dem Business" entsprechende Ordner zur Verfügung stellen, die beim Backup außen vor gelassen werden. Manchmal braucht es nur klare Ansagen.  ;-)   ... man muss ja nicht jeden Quatsch, der angefragt wird, auch umsetzen.


    Live long and prosper!

    (79,108,97,102|%{[char]$_})-join''

    Montag, 24. Februar 2020 10:35
  • Ok ich rudere zurück und gebe zu, dass man einiges auch organisatorisch regeln könnte jedoch würde ich jetzt gerne bestimmte Ordner und deren Unterordner ausschließen. Dort sollen die Dateien nicht bearbeitet werden. Für alle anderen erkannten Dateien soll die Bearbeitung normal ablaufen.

    Sprich ich habe ein Textfile dort stehen Pfade drin

    C:Abteilungen\Abteilung1

    C:Abteilungen\Abteilung2\Chef

    somit soll Abteilung1 Ordner und Unterordner davon sowie Ordner Abteilung2\Chef und Unterordner nicht beachtet werden.

    get-content  C:\Ordnerausnahmedatei.txt somit könnte ich ja den Inhalt auslesen.

    Wie bekomme ich das jetzt noch mit dem Skript oben verarbeitet ?

    Montag, 24. Februar 2020 11:11
  • HIer ... probier das ma:  ;-)

    Die Textdatei könnte so aussehen .... also eine Exclusion pro Zeile

    Abteilung1
    Abteilung2\Chef
    Abteilung32\ChefSekretärin

    ... und so könntest Du dann das Muster für den -match zusammenbauen:

    $ExclusionList = Get-Content -Path C:\_temp\Exclusions.txt 
    $TrimmedStrings = foreach ($Exclusion in $ExclusionList) {
        [REGEX]::Escape($Exclusion.trim())
    }
    $MatchPattern = $TrimmedStrings -join '|'
    $MatchPattern


    Live long and prosper!

    (79,108,97,102|%{[char]$_})-join''

    Montag, 24. Februar 2020 11:54
  • Und wie bastel ich das dann hier rein ?

    Get-ChildItem -Path $Source\* -Include $ext -Recurse -File | 
        Where-Object { $_.lastwritetime -lt $DateBeforeXDays -and $_.FullName -notmatch 'Abteilung1|Abteilung3' } | 
            ForEach-Object { Remove-Item $_.fullname -Force -Verbose -WhatIf }

    würde ich anstatt -notmatch 'Abteilung1|Abteilung2' dann $MatchPattern auswählen ?

    Montag, 24. Februar 2020 12:33
  • würde ich anstatt -notmatch 'Abteilung1|Abteilung2' dann $MatchPattern auswählen ?

    Hmmm .... nee ... anstatt

    -notmatch 'Abteilung1|Abteilung2'

    nimmst Du

    -notmatch $MatchPattern


    Live long and prosper!

    (79,108,97,102|%{[char]$_})-join''

    Montag, 24. Februar 2020 12:37
  • Hi Vielen Dank das funktioniert schon mal prima. Aber hilf mir bitte auf die Sprünge warum nehme ich hier nicht gleich den Parameter $_.DirectoryName und gleiche das mit dem Ordnerpfad_Name ab.

    Dann könnte man doch zusätzlich noch $_.FullName mit Dateipfad_Name abgleichen und somit könnte ich Ordner oder Dateien ausschließen.

    Also sprich zwei MatchPattern und eine -or Verknüpfung (Datum und Ordner oder Datei) etc... .

    Dienstag, 25. Februar 2020 08:04
  • $Source = "C:\Abteilungen"
    $Days = 10
    $ext = "*.txt","*.log"
    $log = "$Source$(get-date -format yymmddHHmmss).txt"
    $DateBeforeXDays = (Get-Date).AddDays(-$Days)
    
    
    
    $ExclusionList = Get-Content -Path "C:\Abteilungen\Ausnahme.txt"
    $TrimmedStrings = foreach ($Exclusion in $ExclusionList) {
        [REGEX]::Escape($Exclusion.trim())
    }
    $MatchPatternOrdner = $TrimmedStrings -join '|'
    
    
    $ExclusionListDatei = Get-Content -Path "C:\Abteilungen\AusnahmeDatei.txt"
    $TrimmedStringsDatei = foreach ($ExclusionDatei in $ExclusionListDatei) {
        [REGEX]::Escape($ExclusionDatei.trim())
    }
    $MatchPatternDatei = $TrimmedStringsDatei -join '|'
    
    
    
    Get-ChildItem -Path $Source\ -Include $ext -Recurse -File | Where-Object { $_.lastwritetime -lt $DateBeforeXDays -and $_.DirectoryName -notmatch $MatchPatternOrdner -and $_.FullName -notmatch $MatchPatternDatei } | ForEach-Object { Remove-Item $_.fullname -Force -Verbose -WhatIf }

    So habe ich den Code jetzt einmal angepasst und das funktioniert soweit ganz gut.

    Kann ich jetzt noch auf eine charmante Weise alle Dateien die gelöscht werden in eine Log_Datei schreiben ?

    Dienstag, 25. Februar 2020 08:50
  • Dafür gibt es das cmdlet 

    out-file

    Das baust du einfach in deine Schleife mit ein.

    Gruß

    Dienstag, 25. Februar 2020 09:17
  • Hi Vielen Dank das funktioniert schon mal prima. Aber hilf mir bitte auf die Sprünge warum nehme ich hier nicht gleich den Parameter $_.DirectoryName und gleiche das mit dem Ordnerpfad_Name ab.

    Wie oben schon erwähnt, kannst Du das Ganze so komplex gestallten, wie das für Deine Aufgabe nötig ist.

    Dann könnte man doch zusätzlich noch $_.FullName mit Dateipfad_Name abgleichen und somit könnte ich Ordner oder Dateien ausschließen.

    Was genau meinst Du mit "Abgleichen"? So lange Du die Ordner und Dateien ohne unerwünschte Nebenwirkungen ausgeschlossen bekommst ... ;-)


    Live long and prosper!

    (79,108,97,102|%{[char]$_})-join''

    Dienstag, 25. Februar 2020 09:57
  • Wie marc-sysadmn schon geschreiben hat, kannst Du dafür Out-File benutzen. Um Deinen Code leichter lesabr zu machen, ist es empfehlenswert, sehr lange Code-Zeilen an den richtigen Stellen zu umbrechen. Hier mal Deine letzte Code-Zeile ein bissl aufgedröselt und um das "Logging" erweitert:
    Get-ChildItem -Path $Source\ -Include $ext -Recurse -File | 
        Where-Object { 
            $_.lastwritetime -lt $DateBeforeXDays -and 
            $_.DirectoryName -notmatch $MatchPatternOrdner -and 
            $_.FullName -notmatch $MatchPatternDatei 
        } | 
            ForEach-Object { 
                $_.FullName | Out-File 'DeletedFiles.log'
                Remove-Item $_.fullname -Force -Verbose -WhatIf 
            }
    Wenn Du mal ein paar Minuten Zeit hast, kannst Du Dir ja mal den The Unofficial PowerShell Best Practices and Style Guide ansehen.


    Live long and prosper!

    (79,108,97,102|%{[char]$_})-join''

    Dienstag, 25. Februar 2020 10:05