使用PowerShell计算文件夹深度

时间:2017-03-16 22:36:42

标签: powershell calculated-columns powershell-v4.0

1。代码说明 别名如何工作

用户在PowerShell中输入目录的路径。代码检查声明的目录中的任何文件夹是否根本不包含任何数据。如果是这样,任何空文件夹的路径将显示在用户的提示上,并最终从系统中删除。

2。问题 别名我正在努力解决

我刚写的代码并没有像我预期的那样计算文件夹层次结构的深度(输出表中的列是空白的)。除此之外,程序运行正常 - 我仍然需要解决我的代码首先删除空父目录和子目录的问题,这当然会在PowerShell中导致错误;例如,采取

C:\Users\JohnMiller\Desktop\Homework

其中HomeworkHomework\Math\School ProjectHomework\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
}

1 个答案:

答案 0 :(得分:2)

深度计数问题:

您的代码引用传递给.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也已删除{ {1}})。

如果删除所有嵌套的空子目录。在前面,你不仅要将你呈现给用户的东西整理一下,而且你可以安全地迭代输出并逐个删除。

使用您的方法,您需要第二步来消除嵌套的空目录。但这里有一个深度优先的递归函数,它省略了嵌套的空文件夹。要使其行为与隐藏文件的代码相同,请传递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 } } 在PSv3 +中可用,它不仅更短,而且效率高于Get-ChildItem -Directory

  • 使用Get-ChildItem | .. Where { $_.PSisContainer -eq $True }代替Write-Host

  • [Console]::WriteLine仅适用于文化不变的字符串文字[System.Convert]::ToBoolean($answer)'True''False'[bool]::TrueString,尽管案例变化和领导和允许尾随空格。