Удалите файлы старше 15 дней с помощью PowerShell

186

Я хотел бы удалить только те файлы, которые были созданы более 15 дней назад в определенной папке. Как я могу сделать это с помощью PowerShell?

user2470170
источник
5
В большинстве ответов используется CreationTime, однако он сбрасывается при копировании файла, поэтому вы можете не получить желаемых результатов. LastWriteTime - это то, что соответствует дате изменения в проводнике Windows.
Роланд Шаер

Ответы:

308

Приведенные ответы будут удалять только файлы (что, как известно, содержится в заголовке этого поста), но вот некоторый код, который сначала удалит все файлы старше 15 дней, а затем рекурсивно удалит все пустые каталоги, которые могли остаться позади. Мой код также использует -Forceопцию для удаления скрытых файлов и файлов только для чтения. Кроме того , я решил не использовать псевдонимы , как OP является новым для PowerShell и не могу понять , что gci, ?, %и т.д. есть.

$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

И, конечно, если вы хотите увидеть, какие файлы / папки будут удалены перед их фактическим удалением, вы можете просто добавить -WhatIfпереключатель к Remove-Itemвызову командлета в конце обеих строк.

Показанный здесь код совместим с PowerShell v2.0, но я также показываю этот код и более быстрый код PowerShell v3.0 в качестве удобных функций многократного использования в моем блоге .

deadlydog
источник
22
Спасибо, что не используете псевдонимы. Если вы новичок в powershell и нашли этот пост в поиске Google, я считаю ваш ответ лучшим.
Джефф Доуди
1
Я попробовал предложение @ deadlydog и, независимо от того, указал ли я -15 или -35 с разными датами создания файла, начиная с месяцев (или последних), он удаляет все содержимое каталога.
Мишель
6
Если файлы могут использоваться, также стоит добавить «-ErrorAction SilentlyContinue» в команду RemoveItem.
Кевин Оуэн
17
Спасибо! Я использую $ _. LastwriteTime вместо $ _. CreationTime
Лаури Луби
2
Вторая команда в этом скрипте всегда получает ошибку, что Get-ChildItem не может найти часть пути. Он получает каталог не найден исключение. Тем не менее, он удаляет пустые папки без проблем. Не уверен, почему он получает ошибку, несмотря на работу.
Натан МакКаскл
51

просто (PowerShell V5)

Get-ChildItem "C:\temp" -Recurse -File | Where CreationTime -lt  (Get-Date).AddDays(-15)  | Remove-Item -Force
Esperento57
источник
16

Другой способ - вычесть 15 дней из текущей даты и сравнить CreationTimeс этим значением:

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

Get-ChildItem $root -Recurse | ? {
  -not $_.PSIsContainer -and $_.CreationTime -lt $limit
} | Remove-Item
Ансгар Вичерс
источник
13

По сути, вы перебираете файлы по заданному пути, вычитаете CreationTimeиз каждого найденного файла текущее время и сравниваете его со Daysсвойством результата. -WhatIfВыключатель будет сказать вам , что будет происходить без удаления файлов (какие файлы будут удалены), снимите переключатель на самом деле удалить файлы:

$old = 15
$now = Get-Date

Get-ChildItem $path -Recurse |
Where-Object {-not $_.PSIsContainer -and $now.Subtract($_.CreationTime).Days -gt $old } |
Remove-Item -WhatIf
Шей Леви
источник
8

Попробуй это:

dir C:\PURGE -recurse | 
where { ((get-date)-$_.creationTime).days -gt 15 } | 
remove-item -force
Роланд Янсен
источник
Я считаю, что последнее -recurseслишком много, нет? Список dir рекурсивно, удаление элемента не должно быть с включенными childs, верно?
Joost
Если каталог, с которым вы работаете, - это два глубоких каталога, необходим второй -recurse.
Брайан С.
5

Сценарий Esperento57 не работает в старых версиях PowerShell. Этот пример делает:

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
источник
1
Я обновил свой ответ, чтобы исключить каталоги, спасибо.
KERR
3

Другой вариант (15. автоматически набирается на [timespan]):

ls -file | where { (get-date) - $_.creationtime -gt 15. } | Remove-Item -Verbose
js2010
источник
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

Это удалит старые папки и его содержимое.

Aigar
источник
0

Если у вас возникли проблемы с приведенными выше примерами на Windows 10, попробуйте заменить .CreationTimeна .LastwriteTime. Это сработало для меня.

dir C:\locationOfFiles -ErrorAction SilentlyContinue | Where { ((Get-Date)-$_.LastWriteTime).days -gt 15 } | Remove-Item -Force
Джефф Блюменталь
источник
LastwriteTimeэто не то же самое CreationTime, LastwriteTimeобновляется каждый раз, когда файл изменяется.
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
источник
Кроме того, он никогда не достигнет оператора else , потому что если $Filesон пуст, он не будет входить в оператор foreach . Вы должны поместить foreach в операторе if .
Дитер
@mati на самом деле это может достигнуть оператора else. У нас есть аналогичный цикл for, основанный на списке файлов, и он регулярно входит в цикл for с переменной $ File как null
BeowulfNode42
Я предполагаю, что так - просто наткнулся на тот же сценарий здесь; networknet.nl/apps/wp/published/…
Шоусон,