删除所有文件并使用 powershell 保持最新

Delete all file and keep the latest using powershell

我有一个每天备份的文件,示例如下:

删除除最新的所有内容之前:

Folder C:\Backup\
File : 
Backup1-Database-A.bak | 1/10/2020 1:24 PM
Backup2-Database-A.bak | 2/10/2020 1:24 PM
Backup1-Database-B.bak | 1/10/2020 1:24 PM
Backup2-Database-B.bak | 2/10/2020 1:24 PM
Backup2-Database-B.bak | 3/10/2020 1:24 PM

删除除最新之外的所有内容后的所需状态:

Folder C:\Backup\
File : 
Backup2-Database-A.bak | 2/10/2020 1:24 PM
Backup2-Database-B.bak | 3/10/2020 1:24 PM

如何为每个数据库保留最新的文件?

我正在使用这个脚本,但它删除了所有 .bak 因此数据库 A 的备份消失了,但我想为每个数据库保留最新的。

$mydays = (Get-Date).AddDays(-7)
$path = "C:\Backup\"
Get-Childitem -path $path -recurse -force | Where-Object { !$_.PSIsContainer -and $_.name -like "*.bak" -and $_.LastWriteTime -lt $mydays} | Remove-Item -Force

正如 Lee_Daily 所建议的,与其使用时间 window 进行过滤,更简单的方法是按上次写入时间对文件进行排序并删除除最新文件以外的所有文件。

挑战在于确定哪些文件与同一个数据库相关,因此应将其视为一个 ,以便您将最新的备份保存在 每组.

下面的代码使用了以下方法:

  • Group-Object cmdlet 允许您按文件名中指示数据库的共享部分对输入文件进行分组。

    • 正在将脚本块 { $_.Name -replace '^Backup\d+-' } 传递给 Group-Object 使用 regex-based 通过删除 'Backup<n>-' 前缀,使其按指示源数据库的共享名称部分对输入文件对象进行分组。
    • 例如,'Backup1-Database-A.bak''Backup2-Database-A.bak' 的结果都只是 'Database-A.bak',所以这两个文件组合在一起。
  • 每个结果组中的文件然后可以按最后写入时间降序排序,
    Sort-Object.

  • 您可以使用 Select-Object -Skip 1.

    从输出中排除第一个(因此也是最近的)文件
  • 生成的文件 - 除了每个数据库的最新文件之外的所有文件 - 然后可以发送到 Remove-Item

$path = 'C:\Backup'
Get-Childitem -Path $path -Recurse -Force -File -Filter *.bak | 
  Group-Object { $_.Name -replace '^Backup\d+-' } | 
    ForEach-Object { 
      $_.Group | Sort-Object LastWriteTime -Descending | Select-Object -Skip 1 |
        Remove-Item -Force -Whatif  
    }

注意:上面命令中的-WhatIf common parameter预览操作。一旦您确定该操作将执行您想要的操作,请删除 -WhatIf

还要注意初始文件选择的简化:-File (PSv3+) 将输出限制为仅文件(不包括目录),-Filter *.bak 是一种按文件扩展名过滤的有效方法。