Usuń pliki starsze niż 15 dni za pomocą PowerShell

186

Chciałbym usunąć tylko pliki, które zostały utworzone ponad 15 dni temu w określonym folderze. Jak mogę to zrobić za pomocą programu PowerShell?

użytkownik2470170
źródło
5
Większość odpowiedzi używa CreationTime, jednak resetuje się, gdy plik jest kopiowany, więc możesz nie uzyskać pożądanych wyników. LastWriteTime odpowiada terminowi „Data modyfikacji” w Eksploratorze Windows.
Roland Schaer

Odpowiedzi:

308

Podane odpowiedzi usuwają tylko pliki (co wprawdzie jest w tytule tego postu), ale oto kod, który najpierw usunie wszystkie pliki starsze niż 15 dni, a następnie rekurencyjnie usunie wszystkie puste katalogi, które mogły pozostać za. Mój kod wykorzystuje również -Forceopcję usuwania plików ukrytych i tylko do odczytu. Również wybrałem, aby nie używać aliasów jako OP jest nowy PowerShell i nie może zrozumieć, co gci, ?, %, itd. Są.

$limit = (Get-Date).AddDays(-15)
$path = "C:\Some\Path"

# Delete files older than the $limit.
Get-ChildItem -Path $path -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt $limit } | Remove-Item -Force

# Delete any empty directories left behind after deleting the old files.
Get-ChildItem -Path $path -Recurse -Force | Where-Object { $_.PSIsContainer -and (Get-ChildItem -Path $_.FullName -Recurse -Force | Where-Object { !$_.PSIsContainer }) -eq $null } | Remove-Item -Force -Recurse

I oczywiście, jeśli chcesz zobaczyć, które pliki / foldery zostaną usunięte przed ich faktycznym usunięciem, możesz po prostu dodać -WhatIfprzełącznik doRemove-Item wywołania polecenia cmdlet na końcu obu wierszy.

Kod pokazany tutaj jest zgodny z PowerShell v2.0, ale pokazuję ten kod i szybszy kod PowerShell v3.0 jako przydatne funkcje wielokrotnego użytku na moim blogu .

śmiertelny pies
źródło
22
Dziękujemy za nieużywanie aliasu. Dla kogoś, kto jest nowy w PowerShell i znalazł ten post za pomocą wyszukiwarki Google, uważam twoją odpowiedź za najlepszą.
Geoff Dawdy
1
Wypróbowałem sugestię @ deadlydog i bez względu na to, czy podam -15 lub -35 ze zmiennymi datami tworzenia plików w poprzednich miesiącach (lub ostatnich), usuwa całą zawartość katalogu.
Michele
6
Jeśli pliki mogą być w użyciu, warto również dodać „-ErrorAction SilentlyContinue” do polecenia RemoveItem.
Kevin Owen,
17
Dzięki! Używam $ _. LastwriteTime zamiast $ _. CreationTime
Lauri Lubi
2
Drugie polecenie w tym skrypcie zawsze powoduje błąd, że Get-ChildItem nie może znaleźć części ścieżki. Otrzymuje wyjątek nie znaleziony katalog. Jednak bez problemu usuwa puste foldery. Nie jestem pewien, dlaczego mimo działania pojawia się błąd.
Nathan McKaskle
51

po prostu (PowerShell V5)

Get-ChildItem "C:\temp" -Recurse -File | Where CreationTime -lt  (Get-Date).AddDays(-15)  | Remove-Item -Force
Esperento57
źródło
16

Innym sposobem jest odjęcie 15 dni od bieżącej daty i porównanie CreationTimez tą wartością:

$root  = 'C:\root\folder'
$limit = (Get-Date).AddDays(-15)

Get-ChildItem $root -Recurse | ? {
  -not $_.PSIsContainer -and $_.CreationTime -lt $limit
} | Remove-Item
Ansgar Wiechers
źródło
13

Zasadniczo iterujesz pliki pod daną ścieżką, odejmujesz CreationTimekażdy znaleziony plik od bieżącego czasu i porównujesz z Dayswłaściwością wyniku. -WhatIfPrzełącznik powie, co się stanie, bez faktycznie usuwanie plików (które zostaną usunięte pliki), usunąć przełącznik faktycznie usunąć pliki:

$old = 15
$now = Get-Date

Get-ChildItem $path -Recurse |
Where-Object {-not $_.PSIsContainer -and $now.Subtract($_.CreationTime).Days -gt $old } |
Remove-Item -WhatIf
Shay Levy
źródło
8

Spróbuj tego:

dir C:\PURGE -recurse | 
where { ((get-date)-$_.creationTime).days -gt 15 } | 
remove-item -force
Roland Jansen
źródło
Uważam, że ostatni -recurseto za dużo, nie? Lista reżimów jest rekurencyjna, usunięcie elementu nie powinno dotyczyć dzieci, prawda?
Joost
Jeśli katalog, z którym pracujesz, ma głębokość dwóch katalogów, potrzebna jest druga sekwencja.
Bryan S.,
5

Skrypt Esperento57 nie działa w starszych wersjach PowerShell. Ten przykład:

Get-ChildItem -Path "C:\temp" -Recurse -force -ErrorAction SilentlyContinue | where {($_.LastwriteTime -lt  (Get-Date).AddDays(-15) ) -and (! $_.PSIsContainer)} | select name| Remove-Item -Verbose -Force -Recurse -ErrorAction SilentlyContinue
KERR
źródło
1
Zaktualizowałem swoją odpowiedź, aby wykluczyć katalogi teraz, dzięki.
KERR
3

Inna alternatywa (15. zostaje automatycznie wpisany na [przedział czasowy]):

ls -file | where { (get-date) - $_.creationtime -gt 15. } | Remove-Item -Verbose
js2010
źródło
1
$limit = (Get-Date).AddDays(-15)
$path = "C:\Some\Path"

# Delete files older than the $limit.
Get-ChildItem -Path $path -Force | Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt $limit } | Remove-Item -Force -Recurse

Spowoduje to usunięcie starych folderów i ich zawartości.

Aigar
źródło
0

Jeśli występują problemy z powyższych przykładów na polu Windows 10, spróbuj wymienić .CreationTimez .LastwriteTime. To zadziałało dla mnie.

dir C:\locationOfFiles -ErrorAction SilentlyContinue | Where { ((Get-Date)-$_.LastWriteTime).days -gt 15 } | Remove-Item -Force
Jeff Blumenthal
źródło
LastwriteTimeto nie to samo co CreationTime, LastwriteTimeaktualizuje się za każdym razem, gdy plik jest modyfikowany.
MisterSmith
-1
#----- Define parameters -----#
#----- Get current date ----#
$Now = Get-Date
$Days = "15" #----- define amount of days ----#
$Targetfolder = "C:\Logs" #----- define folder where files are located ----#
$Extension = "*.log" #----- define extension ----#
$Lastwrite = $Now.AddDays(-$Days)

#----- Get files based on lastwrite filter and specified folder ---#
$Files = Get-Children $Targetfolder -include $Extension -Recurse | where {$_.LastwriteTime -le "$Lastwrite"}

foreach ($File in $Files)
{
    if ($File -ne $Null)
    {
        write-host "Deleting File $File" backgroundcolor "DarkRed"
        Remove-item $File.Fullname | out-null
    }
    else
        write-host "No more files to delete" -forgroundcolor "Green"
    }
}
Ikruzzz
źródło
Ponadto nigdy nie osiągnie instrukcji else , ponieważ jeśli $Filesjest pusta, nie wejdzie do instrukcji foreach . Powinieneś umieścić foreach w instrukcji if .
Dieter
@ mati faktycznie może dotrzeć do instrukcji else. Mamy podobną pętlę for opartą na liście plików i regularnie wchodzi ona do pętli ze zmienną $ File jako null
BeowulfNode42
Chyba tak - natknąłem się tutaj na ten sam skrypt; networknet.nl/apps/wp/published/…
Shawson