【问题标题】:Script to enforce backup retention policy强制执行备份保留策略的脚本
【发布时间】:2019-04-26 06:06:49
【问题描述】:

我需要一个脚本来查看我们的备份文件夹(我们对计算机进行完整备份),并确保我们为每台计算机存储的备份永远不会超过两个最近的备份。我目前正在研究一个 powershell 循环,该循环应该将每个文件名与备份文件夹中的每个其他文件进行比较。每台机器都有多个备份文件,可以通过匹配的前缀和由分隔符分隔的唯一 ID 号来识别这些备份文件。

前缀 = 机器名称和唯一 ID 表示每个备份。

我正在设置外循环并撞到墙上。我将要检查的文件列表存储在$array 中。

我有一个嵌套的 for 循环,我想检查每个文件与数组中的每个其他文件。我有一个查询应该重建数组并在每次迭代时排除当前参考文件。

for ($i=0; $i -lt 5; $i++) { 

$array = Get-ChildItem -Path C:\Users\Aaron.Trujillo\Desktop\test $array = Get-ChildItem -Path C:\Users\Aaron.Trujillo\Desktop\test -Exclude $array[$i]

for ($j=0; $j -lt 5; $j++){ 
    Write-Host "i: $i  j: $j"
    Write-Host "Array i: $($array[$i].name)  Array j: $($array[$j].name)"

    if($array[$i].name -ne $array[$j].name)
    {
        Write-Host "truthval=false"
        $truthval="false"
    } 

    else
    {
        Write-Host "truthval=true"
        $truthval = "true"
    } 
}  

}

我期待这个循环将数组中的前五个文件相互比较(不包括当前参考文件)并更改每个文件的变量,但由于某种原因,参考文件没有被排除在外。

逻辑一定有问题,但我很难发现它。

【问题讨论】:

  • 如果你正在做你似乎正在做的事情......我会使用Group-Object。您可以使用计算属性进行分组,就像您可以使用 Select-Object 的计算属性一样。 [咧嘴一笑]

标签: powershell string-comparison


【解决方案1】:

我发现您的代码存在一些缺陷。

  1. 由于 $array 可能由 Get-ChildItem 填充(在 ntfs 格式的驱动器上返回 排序 输出),因此根本不需要嵌套循环。
    当用一个 for 迭代时,只需与前任/跟随者 index +/- 1 进行比较。

  2. 由于名称根据您的描述包含一个 ID,因此它们总是不同的。所以你必须在模糊的分隔符处拆分名称,并检查机器名称是否相同。

  3. 您的 if 命令不会发出任何内容,它只是在每次迭代时覆盖相同的变量。

使用@Lee_Dailey 的分组好主意,您可以即时拆分名称并检查每个组的计数,按 LastWriteTime 对每个组的文件进行排序,只保留最新的 2 个。

所以给定一个假设的文件树

> tree /F
A:.
└───Backup
        Alpha_8.bak
        Bravo_2.bak
        Bravo_5.bak
        Bravo_6.bak
        Bravo_7.bak
        Bravo_9.bak
        Charlie_1.bak
        Charlie_10.bak
        Charlie_3.bak
        Charlie_4.bak

这个小脚本:

$BackupDir = 'A:\Backup'
$Delim     = '_'

Get-ChildItem -Path $BackupDir -File | 
  Group-Object {($_.BaseName -split $Delim)[0]}

产量:

Count Name                      Group
----- ----                      -----
    1 Alpha                     {Alpha_8.bak}
    5 Bravo                     {Bravo_2.bak, Bravo_5.bak, Bravo_6.bak, Bravo_7.bak...}
    4 Charlie                   {Charlie_1.bak, Charlie_10.bak, Charlie_3.bak, Charlie_4.bak}

然后您可以通过任何方式迭代组并删除每个组的文件,
例如,每台机器删除 2 个最新(按 LastWriteTime 定义)文件之外的所有文件:

Get-ChildItem -Path $BackupDir -File | 
  Group-Object {($_.BaseName -split $Delim)[0]} | ForEach-Object {
    $_.Group | Sort LastWriteTime -Desc | Select -skip 2 | Remove-Item -WhatIf
  }

如果输出看起来正常,请删除尾随 -WhatIf

【讨论】:

  • 谢谢你。我相信你可以告诉我,我还是 powershell 的新手。你介意解释一下你的代码的第二行是如何工作的吗?另外,你有什么推荐的学习powershell的资源吗?我刚开始使用它,但我肯定看到这对我学习至关重要。
  • 虽然我买了 2 本书并阅读了它们(我要证明的不是很透彻),但我从阅读中学到了最多的东西Stack Overflow 上的帮助,从阅读开始powershell 标签info
【解决方案2】:

我认为是$array[$j.name] 周围的括号,即它应该是:

if($array[$i].name -ne $array[$j].name)

编辑:

要进行故障排除,请尝试手动输出您的信息:

for ($i=0; $i -lt 5; $i++) { 

    for ($j=$i+1; $j -lt 5; $j++){ 
        Write-Host "i: $i  j: $j"
        Write-Host "Array i: $($array[$i].name)  Array j: $($array[$j].name)"

        if($array[$i].name -ne $array[$j].name)
        {
            Write-Host "truthval=false"
            $truthval="false"
        } 

        else
        {
            Write-Host "truthval=true"
            $truthval = "true"
        } 
    }  
}

【讨论】:

  • 很好,我解决了这个问题,脚本运行没有错误。虽然逻辑很好,但肯定有问题。 $truthval 变量根本没有更新。
  • 我认为您必须更改更新 $truthval 的方式,因为正如它所写的那样,$truthval 将始终是最后一次比较的值(即您不断在循环中覆盖它)
  • 我知道我需要这样做,但目前该变量包含值“null”,这是我初始化它的值。这意味着它根本没有更新。
  • @amatthew382 试试上面编辑中的代码,看看发生了什么。
  • 看起来代码正在改变 $truthval,但是一旦循环退出 $truthval 仍然被评估为 null。此外,随着循环的进行,参考文件逐渐与更少的文件进行比较。
猜你喜欢
  • 1970-01-01
  • 2019-09-11
  • 2017-11-26
  • 1970-01-01
  • 2015-09-05
  • 1970-01-01
  • 2014-07-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多