我不要想要“删除超过 X 天的文件”。如果我想这样做,我只需选择已经为此目的编写的数千个脚本中的一个,我不会在 ServerFault 上问这么简单的问题。
我做想要删除特定文件夹中除最近的 N 个文件之外的所有文件。
背景:远程系统配置为将定期存档文件转储到 Windows 服务器上的共享中。这些文件的命名约定为 YYYYMMDD-hhmm.ext。如果存档过程失败,我不希望清除脚本仅仅因为文件超过这么多天就删除它们。没有办法将远程系统配置为在存档过程中清除文件。
例如,当脚本运行时,文件夹中可能有 10 个文件,可能有 7 个文件,可能有 5 个文件。我需要始终保留至少最近的 5 个文件,无论它们有多旧。
可以用 PowerShell 完成这个吗?
编辑:最好忽略不符合命名约定的文件或文件夹。其他文件和文件夹不应被删除,也不应混淆脚本(导致保留少于 5 个存档文件)。
答案1
用法: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
}
我不认为这真的比@John 的更好,我只是为了尝试参数、正则表达式而不是使用循环而这样做的。执行正则表达式匹配确实可能有助于排除其他带有 .ext 的、与格式不匹配的文件(例如 20130504-1200.txt.ext、20.ext),但这是否适用值得怀疑。
我很沮丧地发现,如果 $NumberToSave = $items.Count,则需要 if 语句,否则它不会存在。从技术上讲:
$items[$numberToSave..$items.Count] | Remove-Item
工作正常(如果引用超出数组边界,PowerShell 似乎不会出错,它只是处理并忽略它?)但这似乎可能会造成混淆。
答案2
$n = x
$items = Get-ChildItem path_to_folder\*.ext
$items |
Sort-Object Name -Descending |
Select-Object -Last ($items.count - $n) |
Foreach-Object { Remove-Item $_ }
答案3
# Get all the items in `C:\Archive`
Get-ChildItem -Path 'C:\Archive' |
# Skip directories
Where-Object { -not $_.PsIsContainer } |
# Only get files that match YYYYMMDD-HHMM.ext format
Where-Object { $_.Name -match '\d{8}-\d{4}.ext' } |
# Sort them by name, from most recent to oldest
Sort-Object -Descending -Property Name |
# Keep the first five items
Select-Object -Skip 5 |
Remove-Item -WhatIf
答案4
这对我使用 powershell v5.1 有用
Get-ChildItem -Path C:\Path\To\Logs\BaseName*.log | Sort-Object -Descending | Select-Object -Skip 5 | Remove-Item