Храните x количество файлов и удаляйте все остальные - Powershell

Я пытаюсь написать script, который будет просматривать набор папок и хранить только последние 10 файлов. Файлы в каждой папке могут создаваться ежедневно, еженедельно или ежемесячно. Мне нужно script сохранить 10 последних копий независимо от даты создания или измененной даты.

Используя другое сообщение, я создал ниже script, но он не хранит 10 копий, он держит любой файл, который не старше 10 дней.

$ftppath = "C:\Reports"
Get-ChildItem $ftppath -recurse *_Report_*.zip -force|where {$_.lastwritetime -lt (get-date).adddays(-10)} |Remove-Item -force

Любая идея о том, как я могу настроить эту работу? Если я использую script ниже, он работает, но только если я не установил -Recurse. Если вы используете переключатель -Recurse, вы получите ошибку, указанную ниже script.

# Keeps latest 10 files from a directory based on Creation Time

#Declaration variables
$path = "C:\Reports"                               # For example $path= C:\log\*.tmp
$total= (ls $path).count - 10 # Change number 5 to whatever number of objects you want to keep
# Script
ls $path |sort-object -Property {$_.CreationTime} | Select-Object -first $total | Remove-Item -force

Ошибка: Select-Object: не удается проверить аргумент в параметре "Первый". Аргумент -7 меньше минимально допустимого диапазона 0. Поставьте аргумент, который больше 0, а затем повторите попытку.

Ответы

Ответ 1

Вы можете сортировать по CreationTime по убыванию и пропустить первый 10. Если файлов меньше 10, оно не будет удалено.

gci C:\temp\ -Recurse| where{-not $_.PsIsContainer}| sort CreationTime -desc| 
    select -Skip 10| Remove-Item -Force

Ответ 2

Обновление

$path = "C:\TestDir"

# Create 12 test files, 1 second after each other
1..12 | % {
    Remove-Item -Path "$path\$_.txt" -ea SilentlyContinue
    $_ | Out-File "$path\$_.txt"
    Start-Sleep -Seconds 1
}

$files = Get-ChildItem -Path $path -Recurse | Where-Object {-not $_.PsIsContainer}
$keep = 10
if ($files.Count -gt $keep) {
    $files | Sort-Object CreationTime | Select-Object -First ($files.Count - $keep) | Remove-Item -Force -WhatIf
}

Удалите параметр -WhatIf до Remove-Item, когда вы готовы для удаления в реальном времени.

Ответ 3

@Andy: Мой представитель слишком мал, чтобы комментировать, отправляя ответ. Если вы получаете странные результаты, возможно, это связано с тем, что вы смотрите в проводнике Windows, который по умолчанию показывает дату последнего изменения вместо даты создания. Чтобы получить результаты, соответствующие показанным в проводнике Windows, замените LastWriteTime на CreationTime следующим образом:   gci C:\temp\-Recurse | где {-not $_. PsIsContainer} | Сортировка LastWriteTime -desc   | выберите -Skip 10 | Удалить-Item -Force

Ответ 4

Как вызвать эту команду GCI на сервере SQL, пробовал код ниже, но возвращая ошибку

declare @deleteoldtempxe nvarchar(1000)
        set @deleteoldtempxe='powershell.exe gci '+''''+ 'I:\New folder\'+''''+' -Recurse| where{-not $_.PsIsContainer}| sort CreationTime -desc| 
    select -Skip 1| Remove-Item -Force'
    select @deleteoldtempxe

EXEC master.dbo.xp_cmdshell @deleteoldtempxe