PowerShell:以迭代方式从文件夹子树中删除所有空子文件夹

PowerShell: Iteratively remove all empty subfolders from a folder subtree

提问人:Brian 提问时间:6/17/2023 最后编辑:mklement0Brian 更新时间:6/18/2023 访问量:61

问:

我编写了以下脚本来递归删除任何空文件夹。我已经在沙盒中对此进行了测试,它似乎是安全的。也就是说,它只会删除一个为空的文件夹,并且它只会在起始父文件夹内的子文件夹中导航,并且不会无意中在目录中进一步向上移动。

所以,如果你能快速看一下我的剧本,并告诉我你是否看到任何危险,我将不胜感激。谢谢!

$isEmpty=1
$iteration=0
while ($isEmpty) {
    $isEmpty=0
    $iteration++
    
    get-childitem -Directory -Force -recurse | ForEach-Object {
        $count=(Get-ChildItem -Path $_.FullName -Force).count
        if ($count -eq 0) {
            $isEmpty=1
            Write-Host "$iteration`t$count`t$_"
            $path="\\?\"+$_.FullName
            $folder= Get-item -Path $path
            $folder.Attributes = $folder.Attributes -band -bnot [System.IO.FileAttributes]::ReadOnly
            $folder.Attributes = $folder.Attributes -band -bnot [System.IO.FileAttributes]::Hidden

            Remove-Item -Force -LiteralPath $path
        }
    }
    
}
PowerShell 目录 为空 子树 delete-directory

评论

1赞 Bitcoin Murderous Maniac 6/17/2023
很明显,没有太多的是在确保备份数据以防万一并确认在带有参数的输出中没有看到任何陷阱后,运行并检查生产路径上的输出。Remove-Item -Force -LiteralPath $path -WhatIf-whatif

答:

0赞 mklement0 6/17/2023 #1

$isEmpty=1,$isEmpty=0

虽然 和 确实作为隐式布尔值工作,但最好式使用布尔值,即 和:10$true$false$isEmpty = $true$isEmpty = $false


Get-ChildItem -Path $_.FullName

如果您知道路径是文本(逐字)路径而不是通配符表达式,请使用 代替 .-LiteralPath-Path


Get-Item -Path $path

该建议同样适用,但更重要的是:-LiteralPath

  • 也许令人惊讶的是 - 请参阅 GitHub 问题 #6502 - 即使通过显式文本路径定位文件系统项 - 也需要使用 Get-Item 或 Get-ChildItem 来定位隐藏项。-Force

$folder.Attributes = $folder.Attributes -band -bnot [System.IO.FileAttributes]::ReadOnly[...]

无需显式清除文件系统项中的 and 属性即可让 Remove-Item 删除它们 - 使用 就足够了。HiddenReadOnly-Force


退后一步:

如果自下而上处理目录(文件夹),即从目录子树中的目录开始,然后迭代向上遍历,则可以避免文件夹子树的多次遍历:

Get-ChildItem -Directory -Force -Recurse | 
  Sort-Object -Descending { ($_.FullName -split '[\\/]').Count } |
  Where-Object { 
    if (-not ($_ | Get-ChildItem -Force | Select-Object -First 1)) {
      $_ | Remove-Object -Force -WhatIf
    }
  }

注意:

  • 上述命令中的 -WhatIf 通用参数可预览操作。一旦确定操作将执行所需的操作,请删除并重新执行。-WhatIf

  • 也就是说,考虑到任务的迭代性质,只会显示将被删除的空目录,而不会显示因删除任何叶子而也会被删除的任何祖先-WhatIf

    • 只有实际运行命令(通过删除)才会告诉您实际结果。-WhatIf
    • 因此,最好在调整代码时保留整个目录子树的备份