Powershell script to delete oldest files (not relative to current date)
I DO NOT want to "delete files older than X days." If I wanted to do this, I'd just pick one of the thousands of scripts out there that have already been written for that purpose, and I wouldn't bother asking such a trivial question on ServerFault.
I DO want to delete all but the most recent N files in a particular folder.
Background: a remote system is configured to dump a periodic archive files to a share on a Windows server. These files have a naming convention of YYYYMMDD-hhmm.ext. Should the archive process fail, I don't want the purge script to delete the files just because they are older than so-many-days. There is no way to configure the remote system to purge the files as part of the archive process.
So for example, when the script runs there may be 10 files, there may be 7 files, there may be 5 files in the folder. I need to always keep at least the most recent 5, regardless of how old they are.
Can this be done with PowerShell?
EDIT: it would be desirable to ignore files or folders not matching the naming convention. Other files and folders shouldn't be deleted, nor should they confuse the script (resulting in the retention of fewer than 5 archive files).
Usage: yourScript.ps1 -Path path\to\run\against [-NumberToSave N]
param([String]$Path,[Int32]$NumberToSave=5)
$items = Get-ChildItem "$Path\*.ext" |
Where-Object Name -match "\d\d\d\d\d\d\d\d-\d\d\d\d\.ext" |
Sort-Object Name -Descending
if ($NumberToSave -lt $items.Count)
{
$items[$NumberToSave..($items.Count-1)] | Remove-Item
}
I don't expect this is really any better than @John's, I just made this to try parameters, regexp, and not using a loop. Doing a regex match does have the possible benefit of ruling out other files with .ext that don't match the format (e.g. 20130504-1200.txt.ext, 20.ext), but it's doubtful that applies.
I was bummed to find out that if $NumberToSave = $items.Count then the if statement is needed, otherwise it wouldn't be there. Technically:
$items[$numberToSave..$items.Count] | Remove-Item
works fine (PowerShell doesn't seem to error if you reference past the array bounds, it just handles and ignores it?) but that seemed potentially confusing.
$n = x
$items = Get-ChildItem path_to_folder\*.ext
$items |
Sort-Object Name -Descending |
Select-Object -Last ($items.count - $n) |
Foreach-Object { Remove-Item $_ }