1.代码说明别名如何工作
用户在PowerShell中输入目录的路径。代码检查声明的目录中的任何文件夹是否根本不包含任何数据。如果是这样,任何空文件夹的路径将显示在用户的提示上,并最终从系统中删除。
2.问题别名我正在努力解决的问题
我刚写的代码没有像我期望的那样计算文件夹层次结构的深度(输出表中的列是空白的)。除此之外,程序运行正常 - 我仍然需要解决我的代码首先删除空父目录和子目录的问题,这当然会在PowerShell中导致错误;例如,拿走
C:\Users\JohnMiller\Desktop\Homework
其中Homework
由Homework\Math\School Project
和Homework\Computer Science\PowerShell Code
组成。请注意,除PowerShell Code
(包含此脚本的文件夹)外,所有目录都应为空。 (旁注:当没有文件驻留在内部时,文件夹被认为是空的。至少这是我的代码现在所基于的。)
3.守则
# Delete all empty (sub)folders in [$path]
[Console]::WriteLine("`n>> Start script for deleting all empty (sub)folders.")
$path = Read-Host -prompt ">> Specify a path"
if (test-path $path)
{
$allFolders = Get-ChildItem $path -recurse | Where {$_.PSisContainer -eq $True}
$allEmptyFolders = $allFolders | Where-Object {$_.GetFiles().Count -eq 0}
$allEmptyFolders | Select-Object FullName,@{Name = "FolderDepth"; Expression = {$_.DirectoryName.Split('\').Count}} | Sort-Object -descending FolderDepth,FullName
[Console]::WriteLine("`n>> Do you want do remove all these directories? Validate with [True] or [False].") #'#
$answer = Read-Host -prompt ">> Answer"
if ([System.Convert]::ToBoolean($answer) -eq $True)
{
$allEmptyFolders | Remove-Item -force -recurse
}
else
{
[Console]::WriteLine(">> Termination confirmed.`n")
exit
}
}
else
{
[Console]::WriteLine(">> ERROR: [$($path)] is an invalid directory. Program terminates.`n")
exit
}
您的代码引用传递给.DirectoryName
的计算属性中的Select-Object
属性,但[System.IO.DirectoryInfo]
输出的Get-ChildItem
实例没有此类属性。请改用.FullName
属性:
$allEmptyFolders |
Select-Object FullName,@{Name='FolderDepth'; Expression={$_.FullName.Split('\').Count}} |
Sort-Object -descending FolderDepth,FullName
用一个简单的例子来回顾你的问题:
如果c:\foo
为空(没有文件)但是有空子目录。 c:\foo\bar
,你的代码输出它们两个,如果你然后删除c:\foo
,删除c:\foo\bar
接下来失败(因为删除c:\foo
也删除了c:\foo\bar
)。
如果消除所有嵌套的空子目录。在前面,您不仅要将您呈现的内容整理到用户,还可以安全地迭代输出并逐个删除。
使用您的方法,您需要第二步来消除嵌套的空目录。但这是一个深度优先的递归函数,它省略了嵌套的空文件夹。要使其行为与隐藏文件的代码相同,请传递-Force
。
function Get-RecursivelyEmptyDirectories {
[cmdletbinding()]
param(
[string] $LiteralPath = '.',
[switch] $Force,
[switch] $DoNotValidatePath
)
$ErrorActionPreference = 'Stop'
if (-not $DoNotValidatePath) {
$dir = Get-Item -LiteralPath $LiteralPath
if (-not $dir.PSIsContainer) { Throw "Not a directory path: $LiteralPath" }
$LiteralPath = $dir.FullName
}
$haveFiles = [bool] (Get-ChildItem -LiteralPath $LiteralPath -File -Force:$Force | Select-Object -First 1)
$emptyChildDirCount = 0
$emptySubdirs = $null
if ($childDirs = Get-ChildItem -LiteralPath $LiteralPath -Directory -Force:$Force) {
$emptySubDirs = New-Object System.Collections.ArrayList
foreach($childDir in $childDirs) {
if ($childDir.LinkType -eq 'SymbolicLink') {
Write-Verbose "Ignoring symlink: $LiteralPath"
} else {
Write-Verbose "About to recurse on $($childDir.FullName)..."
try { # If .AddRange() fails due to exceeding the array list's capacity, we must fail too.
$emptySubDirs.AddRange(@(Get-RecursivelyEmptyDirectories -DoNotValidatePath -LiteralPath $childDir.FullName -Force:$Force))
} catch {
Throw
}
# If the last entry added is the child dir. at hand, that child dir.
# is by definition itself empty.
if ($emptySubDirs[-1] -eq $childDir.FullName) { ++$emptyChildDirCount }
}
} # foreach ($childDir ...
} # if ($childDirs = ...)
if (-not $haveFiles -and $emptyChildDirCount -eq $childDirs.Count) {
# There are no child files and all child dirs., if any, are themselves
# empty, so we only output the input path at hand, as the highest
# directory in this subtree that is empty (save for empty descendants).
$LiteralPath
} else {
# This directory is not itself empty, so output the (highest-level)
# descendants that are empty.
$emptySubDirs
}
}
有关您的代码的提示:
Get-ChildItem -Directory
可以在PSv3 +中使用,它不仅更短,而且比Get-ChildItem | .. Where { $_.PSisContainer -eq $True }
更有效。Write-Host
而不是[Console]::WriteLine
[System.Convert]::ToBoolean($answer)
仅适用于文化不变的字符串文字'True'
和'False'
([bool]::TrueString
和[bool]::FalseString
,尽管允许使用案例变体和前导和尾随空格)。