Czyszczenie plików i katalogów – powershell
Temat czyszczenia zawartości dysków pojawia się u nas dość często, było już o czyszczeniu dysku C, pisaliśmy o WinSxS, pojawił się także skrypt usuwający pliki starsze niż zadana ilość dni. Jednak ten ostatni skrypt nie jest doskonały, albowiem usuwa co prawda pliki, ale pozostawia puste katalogi.
Ostatnio zmierzyłem się z problemem czyszczenia zawartości ogromnego udziału z mnóstwem plików i katalogów, gdzie należało usunąć ponad 10 milionów plików starszych niż rok. Pliki jak pliki to żadne problem, wspomniany wcześniej skrypt daje radę, o tyle rzecz jasna pozostaje problem pustych, wyczyszczonych z przestarzałych danych katalogów. Postanowiłem więc nieco przerobić skrypt 🙂
W pierwszym kroku oczywiście należy podać lokalizację oraz określić jak bardzo stare pliki chcemy usuwać. Tak więc w pierwszych linijkach (poza tymi ze skryptu bazowego) wrzucamy:
$limit = (Get-Date).AddDays(-90) $sciezka = "C:\folder\ze\smieciami"
Można tez zapisać to w formie argumentów skryptu, ale to wyjaśnię za chwilę. Następnie wykonujemy rekursywne usuwanie plików starszych niż zadana liczba dni:
Get-ChildItem -Path $sciezka -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt $limit } | Remove-Item -Force
To polecenie usunie wszystkie pliki starsze niż… Tu warto wtrącić, że polecenie będzie wykonywało się jakąś dłuższą chwilę jeśli mamy do „przeczesania” solidną ilość plików i katalogów. Kolejna linijka usunie puste katalogi:
Get-ChildItem -Path $sciezka -Recurse -Force | Where-Object { $_.PSIsContainer -and (Get-ChildItem -Path $_.FullName -Recurse -Force | Where-Object { !$_.PSIsContainer }) -eq $null } | Remove-Item -Force -Recurse
To także zajmie troszkę czasu. Dla mniej więcej 12 milionów plików i około 5 milionów katalogów cały skrypt wykonywał się 48 godzin 🙂 także lepiej uzbroić się w cierpliwość 😉 A możne ktoś wie jak to przyspieszyć? Tak czy inaczej cały skrypt w wersji z „zakodowanymi na twardo danymi” wygląda tak:
Clear $ErrorActionPreference = "SilentlyContinue" Remove-Variable [a..z]* -Scope Global Remove-Variable [1..9]* -Scope Global $limit = (Get-Date).AddDays(-90) $sciezka = "C:\folder\ze\smieciami" #Usuniecie plikow starszych niz $limit. Get-ChildItem -Path $sciezka -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt $limit } | Remove-Item -Force #Usuniecie wszystkich pustych katalogow pozostalych po czyszczeniu powyzej. Get-ChildItem -Path $sciezka -Recurse -Force | Where-Object { $_.PSIsContainer -and (Get-ChildItem -Path $_.FullName -Recurse -Force | Where-Object { !$_.PSIsContainer }) -eq $null } | Remove-Item -Force -Recurse
Zaś w wersji sparametryzowanej:
Clear $ErrorActionPreference = "SilentlyContinue" Remove-Variable [a..z]* -Scope Global Remove-Variable [1..9]* -Scope Global $dni = 0 -$args[0] $limit = (Get-Date).AddDays($dni) $sciezka = $args[1] #Usuniecie plikow starszych niz $limit. Get-ChildItem -Path $sciezka -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt $limit } | Remove-Item -Force #Usuniecie wszystkich pustych katalogow pozostalych po czyszczeniu powyzej. Get-ChildItem -Path $sciezka -Recurse -Force | Where-Object { $_.PSIsContainer -and (Get-ChildItem -Path $_.FullName -Recurse -Force | Where-Object { !$_.PSIsContainer }) -eq $null } | Remove-Item -Force -Recurse
Tak zapisany skrypt uruchamiamy w postaci:
czyszczenie_dysku.ps1 90 C:\sciezka\do\katalogu
Macie jakieś lepsze i szybsze pomysły na pozbycie się zalegających śmieci na serwerach Windowsowych?
Najnowsze komentarze