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?


Podobne Tematy: