如何在 PowerShell 中删除空文件夹

有效的目录管理在 PowerShell 脚本中至关重要,而 Get-ChildItem
cmdlet 是导航文件系统的基石。在清理空文件夹的任务中,遍历文件夹层次结构变得至关重要。
本文深入探讨了 Get-ChildItem
与其他 cmdlet 的实际用法,以系统地识别并删除指定路径中的空目录。通过利用 PowerShell 强大的脚本能力,用户能够有效管理目录,确保文件系统的良好组织。
PowerShell 中的 Get-ChildItem
Cmdlet
Get-ChildItem
cmdlet 用于检索指定位置的所有子项(文件和文件夹)。当需要删除给定文件夹路径下的所有空文件夹时,遍历文件夹层次结构是必须的。
因此,Get-ChildItem
cmdlet 将非常有用。此 cmdlet 接受 Recurse
和 Directory
等参数,以获取目录类型的子项并递归遍历文件夹结构。
语法:
Get-ChildItem -Path -Directory -Recurse
还有许多可选参数可供使用。让我们创建如下所示的文件夹结构。
somepath/testA
testB
testD
testE
a.txt
testC
testF
b.txt
testG
testH
其目的是删除 testA
文件夹中的所有空文件夹。因此,以下文件夹应被删除。
testD
testG
testH
让我们获取给定文件夹路径(somepath/testA
)中的所有子目录。
$path = "D:\testA"
$fetchedDirList = Get-ChildItem $path -Directory -Recurse
在这个代码片段中,我们将变量 $path
赋值为目录路径 "D:\testA"
,并使用 Get-ChildItem
cmdlet 配合 -Directory
和 -Recurse
参数,以递归方式从指定路径获取所有目录。结果的目录列表存储在变量 $fetchedDirList
中,给我们提供了表示 "D:\testA"
及其子目录中所有目录的目录对象集合。
使用别名 gci
代替 Get-ChildItem
是可能的。
$fetchedDirList = gci $path -directory -Recurse
从原始代码过渡到这个修订版本时,我们继续在变量 $fetchedDirList
中捕获通过 Get-ChildItem
cmdlet 检索到的目录对象。然而,在这个更新的代码中,我们使用别名 gci
而不是完整的 cmdlet 名称 Get-ChildItem
。
这个简写保持了从指定路径 $path
递归获取目录并将其存储在 $fetchedDirList
中的功能。
让我们检查 $fetchedDirList
变量。
$fetchedDirList
输出:
所有目录和子目录已如预期般被获取。
PowerShell 中的 Where-Object
Cmdlet
我们需要从上述结果中过滤出空目录。Where-Object
cmdlet 根据对象的属性从集合中过滤对象。
可以使用 Where
别名代替 Where-Object
命令。我们需要根据每个目录内的项目数量来过滤上述目录列表。
条件如下所示。
where { (gci $_.fullName).count -eq 0 }
当集合中的给定对象的子项数量为 0 时,它被视为空目录。因此,我们应该删除它。
让我们将上一步的输出传递给 Where
cmdlet。
$emptyDirectoryList = $fetchedDirList | where { (gci $_.fullName).count -eq 0 }
在这行代码中,我们将变量 $emptyDirectoryList
赋值为使用 Where
别名从 $fetchedDirList
过滤的目录结果。过滤条件在一个脚本块中定义,检查每个目录的子项数量(通过 gci $_.FullName
获取)是否等于 0。
这种方法有效地识别并捕获表示空目录的目录对象在 $emptyDirectoryList
中。
让我们打印 $emptyDirectoryList
。
$emptyDirectoryList
输出:
结果完全正确。我们得到了只有两个内容为空的文件夹 testD
和 testH
。
我们可以轻松删除 $emptyDirectoryList
集合中的每个对象。可以使用 Remove-Item
cmdlet 删除一个项目。
在此之前,我们需要获取 $emptyDirectoryList
内每个对象的完整路径。Select-Object
cmdlet 可以通过其 FullName
属性获取对象。
$finalListToRemove = $emptyDirectoryList | select -ExpandProperty FullName
在这行代码中,我们通过提取存储在 $emptyDirectoryList
中的目录的完整路径来创建一个新变量 $finalListToRemove
。我们利用 Select-Object
cmdlet 的 -ExpandProperty FullName
参数,允许我们检索 $emptyDirectoryList
中每个目录对象的 FullName
属性的值。
因此,$finalListToRemove
包含空目录的完整路径列表,为删除做好了准备。
$finalListToRemove
$finalListToRemove
的输出:
现在我们有了待删除的文件夹列表。
在 PowerShell 中从集合中删除项目
可以使用 ForEach-Object
cmdlet 循环遍历集合中的项目。在循环内部,我们可以使用 Remove-Item
cmdlet。
$finalListToRemove | ForEach-Object { Remove-Item $_ }
$_
表示集合中的当前项目。这将删除 testD
和 testH
文件夹。
这里有一个棘手的地方。当 testH
文件夹被删除时,testG
目录也变得空了。
因此,我们需要对脚本进行一些改动。我们应该运行上述过程,直到剩下的都是非空文件夹。
我们可以使用 do...while
循环来做到这一点。
$path = "D:\testA"
do {
$fetchedDirList = Get-ChildItem $path -Directory -Recurse
$emptyDirectoryList = $fetchedDirList | where { (gci $_.fullName).count -eq 0 }
$finalListToRemove = $emptyDirectoryList | select -ExpandProperty FullName
$finalListToRemove | ForEach-Object { Remove-Item $_ }
} while ( $finalListToRemove.count -gt 0 )
在这段代码块中,我们设置了一个循环,以系统地检测并删除指定路径及其子目录内的空目录。在循环内部,我们首先使用 Get-ChildItem
cmdlet 从指定路径递归获取所有目录。
然后,我们使用 Where-Object
cmdlet 过滤出空目录。在提取这些空目录的完整路径后,我们继续使用 ForEach-Object
循环逐一删除它们。
这个循环会迭代,只要还有剩余的空目录可供删除,确保彻底清理指定路径及其子目录中的空目录。
当需要考虑隐藏文件和文件夹时,我们可以向 Get-ChildItem
cmdlet 传递 -Force
参数,如下所示。
$emptyDirectoryList = $fetchedDirList | where { (gci $_.fullName -Force).count -eq 0 }
输出:
结论
在 PowerShell 中,有效识别和删除空文件夹对于维护有序的文件系统至关重要。通过战略性地利用像 Get-ChildItem
、Where-Object
和 Remove-Item
这样的 cmdlet,用户可以简化目录管理任务。
这些 cmdlet 能够全面清理指定路径中的目录,提高系统效率和组织。通过利用 PowerShell 的脚本环境,用户可以自动化目录管理流程,节省时间和精力,同时确保文件系统的整洁。
通过 PowerShell 强大的功能,目录管理成为系统管理的无缝部分,使用户能够保持最佳的系统性能。
Nimesha is a Full-stack Software Engineer for more than five years, he loves technology, as technology has the power to solve our many problems within just a minute. He have been contributing to various projects over the last 5+ years and working with almost all the so-called 03 tiers(DB, M-Tier, and Client). Recently, he has started working with DevOps technologies such as Azure administration, Kubernetes, Terraform automation, and Bash scripting as well.