删除Powershell中具有序列化名称的文件夹

时间:2019-01-02 13:00:18

标签: windows powershell

我的问题可能\可能不会很复杂,但是我一直在抓挠头,寻找解决方法,但是到目前为止并没有提出太多建议。

我的文件夹结构如下:

C:\
└───ParentFolder
    ├───ChildFolder1
    │   ├───SubFolderA_1
    │   ├───SubFolderA_2
    │   ├───SubFolderA_3
    │   ├───SubFolderA_4
    │   ├───SubFolderB_1
    │   ├───SubFolderB_2
    │   ├───SubFolderB_3
    │   └───SubFolderB_4
    └───ChildFolder2
        ├───SubFolderA_1
        ├───SubFolderA_2
        ├───SubFolderA_3
        ├───SubFolderA_4
        ├───SubFolderB_1
        ├───SubFolderB_2
        ├───SubFolderB_3
        └───SubFolderB_4

我正在寻找的是一个PowerShell脚本,该脚本将利用“ SubFolders”名称的序列化性质来删除较旧的版本,而仅保留最新的SubFolders。

使用上面的示例,这意味着脚本会将SubFolderA_1删除为SubFolderA_3,将SubFolderB_1删除为SubFolderB_3,仅在ChildFolders中保留SubFolderA_4和SubfolderB_4。

有人会知道这样做的方法吗?我当时在考虑对象排序+递归函数+模式匹配,但是我似乎一无所获。顺便说一下,我是PS菜鸟。

非常感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

这是一种方法。 [咧嘴]的心脏是Group-Object cmdlet。关于它经常被忽略的一件事是使用计算属性的能力,就像使用Select-Object cmdlet一样。

# fake reading in a list of directories
#    in real life, use Get-ChildItem -Directory
$DirList = @(
    [System.IO.DirectoryInfo]'C:\ParentFolder\ChildFolder1\SubFolderA_1'
    [System.IO.DirectoryInfo]'C:\ParentFolder\ChildFolder1\SubFolderA_2'
    [System.IO.DirectoryInfo]'C:\ParentFolder\ChildFolder1\SubFolderA_3'
    [System.IO.DirectoryInfo]'C:\ParentFolder\ChildFolder1\SubFolderA_4'
    [System.IO.DirectoryInfo]'C:\ParentFolder\ChildFolder1\SubFolderB_1'
    [System.IO.DirectoryInfo]'C:\ParentFolder\ChildFolder1\SubFolderB_2'
    [System.IO.DirectoryInfo]'C:\ParentFolder\ChildFolder1\SubFolderB_3'
    [System.IO.DirectoryInfo]'C:\ParentFolder\ChildFolder1\SubFolderB_4'
    [System.IO.DirectoryInfo]'C:\ParentFolder\ChildFolder2\SubFolderA_1'
    [System.IO.DirectoryInfo]'C:\ParentFolder\ChildFolder2\SubFolderA_2'
    [System.IO.DirectoryInfo]'C:\ParentFolder\ChildFolder2\SubFolderA_3'
    [System.IO.DirectoryInfo]'C:\ParentFolder\ChildFolder2\SubFolderA_4'
    [System.IO.DirectoryInfo]'C:\ParentFolder\ChildFolder2\SubFolderB_11'
    [System.IO.DirectoryInfo]'C:\ParentFolder\ChildFolder2\SubFolderB_22'
    [System.IO.DirectoryInfo]'C:\ParentFolder\ChildFolder2\SubFolderB_3'
    [System.IO.DirectoryInfo]'C:\ParentFolder\ChildFolder2\SubFolderB_44'
)

$GroupedDirList = $DirList |
    # changed from sorting by the FullName to sorting by the trailing number
    #    thanks to LotPings for pointing out the glitch with multi-digit numbers
    Sort-Object {[int]$_.FullName.Split('_')[1]} |
    Group-Object {$_.FullName.Split('_')[0]}

foreach ($GDL_Item in $GroupedDirList)
    {
    $GDL_Item.Group |
        Select-Object -SkipLast 1 |
        ForEach-Object {
            # remove the quotes, the Write-Host, and the "$()" when you do this for real
            # can't use the "-WhatIf" parameter here since the dirs don't actually exist on my system
            Write-Host "Remove-Item -LiteralPath $($_.FullName) -Recurse -WhatIf"
            }

    '=' * 20
    }

输出...

Remove-Item -LiteralPath C:\ParentFolder\ChildFolder1\SubFolderA_1 -Recurse -WhatIf
Remove-Item -LiteralPath C:\ParentFolder\ChildFolder1\SubFolderA_2 -Recurse -WhatIf
Remove-Item -LiteralPath C:\ParentFolder\ChildFolder1\SubFolderA_3 -Recurse -WhatIf
====================
Remove-Item -LiteralPath C:\ParentFolder\ChildFolder1\SubFolderB_1 -Recurse -WhatIf
Remove-Item -LiteralPath C:\ParentFolder\ChildFolder1\SubFolderB_2 -Recurse -WhatIf
Remove-Item -LiteralPath C:\ParentFolder\ChildFolder1\SubFolderB_3 -Recurse -WhatIf
====================
Remove-Item -LiteralPath C:\ParentFolder\ChildFolder2\SubFolderA_1 -Recurse -WhatIf
Remove-Item -LiteralPath C:\ParentFolder\ChildFolder2\SubFolderA_2 -Recurse -WhatIf
Remove-Item -LiteralPath C:\ParentFolder\ChildFolder2\SubFolderA_3 -Recurse -WhatIf
====================
Remove-Item -LiteralPath C:\ParentFolder\ChildFolder2\SubFolderB_3 -Recurse -WhatIf
Remove-Item -LiteralPath C:\ParentFolder\ChildFolder2\SubFolderB_11 -Recurse -WhatIf
Remove-Item -LiteralPath C:\ParentFolder\ChildFolder2\SubFolderB_22 -Recurse -WhatIf
====================

答案 1 :(得分:0)

只要只有一个下划线,

  • 列出带有多个通配符的文件夹
  • 在下划线处分隔全名,然后
  • 按第一部分分组
  • 重复组,
  • 对降序进行排序(如果可能会有多个地方转换为int或使用$ ToNatural),则
  • 跳过第一个
  • 删除剩余文件夹。

这与Lee_Daileys脚本非常相似,但是将对所有数字进行排序,并在所有数字的前面用零填充到唯一宽度。

## $ToNatural from Roman Kuzmin source https://stackoverflow.com/a/5429048/6811411
$ToNatural = { [regex]::Replace($_, '\d+', { $args[0].Value.PadLeft(20,"0") }) }

Get-ChildItem C:\ParentFolder\ChildFolder*\Subfolder* | 
  Group-Object @{e={$_.fullname.split('_')[0]}} | ForEach-Object {
    $_.Group | Sort $ToNatural -Descending | Select -Skip 1 | Remove-Item -WhatIf
  }

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