首页 > 解决方案 > Powershell - 在目录的长文件路径中查找嵌套文件夹的数量

问题描述

任何人都可以帮助我解决 powershell 中的代码难题吗?我正在尝试查看多个远程服务器上的特定目录,并在该目录中找到最深的嵌套子文件夹,然后计算父文件夹的数量。伪代码如下。

  1. $servers = get-content(服务器列表)和 $path =(远程机器上的 targetdir)
  2. 对于 $servers 中的每个 $s:
  3. 找到最长的路径
  4. 计算 \ 的数量(以识别子文件夹的数量)
  5. 将输出写入文件 $Servername $countOfNestedFolders

对不起,我只是足够好 w/ posh 有点危险。

标签: powershellsubdirectorydepth

解决方案


要解决您的核心问题:

对于给定的$path,您可以在其子树中找到最大目录深度- 表示为路径分隔符的数量(\在 Windows 上,/在 Unix 上)加上内部嵌套最深的子目录的完整$path路径中的一个- 如下所示:

# Outputs the number of path components of the most deeply nested folder in $path.
(Get-ChildItem $path -Recurse -Directory | 
   Measure-Object -Maximum { ($_.FullName -split '[\\/]').Count }
).Maximum

注意:如果您想知道相对深度 - 相对于$path,请添加-NameGet-ChildItem调用中并在传递给的脚本块 ( ) 中$_.FullName替换为。then的结果意味着根本没有子目录,意味着只有直接子目录,意味着直接子目录本身(只有)子目录,......$_{ ... }Measure-Object0$path12

  • Get-ChildItem -Recurse -Directory $path输出目录 ( -Directory) 的整个子树中的所有子目录 ( -Recurse) $path;添加-Force以包含隐藏的子目录。- 见Get-ChildItem

  • Measure-Object -Maximum { ($_.FullName -split '[\\/]').Count }计算每个目录的完整路径 ( ) 中路径分隔符的计数 ([\\/]是一个匹配单个\和字符的正则表达式。 ) - 使用脚本块作为 (隐含的)参数,其中表示手头的输入路径 - 并确定最大值 ( ); 给定输出一个实例,通过属性访问原始最大值。/$_.FullName {...}-Property$_-MaximumMeasure-ObjectMicrosoft.PowerShell.Commands.GenericMeasureInfo.Maximum


所有附带的任务 - 将此计算应用于多个服务器,将结果写入服务器特定的文件 - 都可以使用通常的 cmdlet ( Get-ContentForEach-ObjectSet-Content/ )来完成Out-File>


更快的选择:

上面的命令简洁且符合 PowerShell 的习惯,但有点慢。这是一个直接使用 LINQ 和 .NET API 的更快的替代方案:

# Note: Makes sure that $path is a *full* path, because .NET's current
#       directory usually differs from PowerShell's.
1 + [Linq.Enumerable]::Max(
  ([System.IO.Directory]::GetDirectories(
    $path, '*', 'AllDirectories'
  ) -replace '[^\\/]').ForEach('Length')
)

注意:上述内容也总是包含隐藏目录。在 .NET Core / .NET 5+ 中,[System.IO.Directory]::GetDirectories()现在提供了一个额外的重载,可提供对枚举的更多控制。


也列出最大深度目录:

如果您不仅想计算最大深度,还想列出所有具有最大深度的目录(注意可以有多个):

# Sample input path.
# Note: Makes sure that $path is a *full* path, because .NET's current
#       directory usually differs from PowerShell's.
$path = $PWD

# Extract all directories with the max. depth using Group-Object:
# Group by the calculated depth and extract the last group, which relies on
# Group-Object outputting the results sorted by grouping criteria.
$maxDepthGroup = 
  [System.IO.Directory]::GetDirectories($path, '*', 'AllDirectories') | 
    Group-Object { ($_ -split '[\\/]').Count } |
      Select-Object -Last 1

# Construct the output object.
[pscustomobject] @{
  MaxDepth = $maxDepthGroup.Values[0] # The grouping criterion, i.e. the depth.
  MaxDepthDirs = $maxDepthGroup.Group # The paths comprising the group.
}

输出是一个自定义对象,具有.MaxDepth.MaxDepthDirs(具有最大深度的那些目录的完整路径的数组)属性。如果将其通过管道传输到Format-List,您将得到如下信息:

MaxDepth     : 6
MaxDepthDirs : {/Users/jdoe/Documents/Ram Dass Audio Collection/The Path of Service, /Users/jdoe/Documents/Ram Dass Audio Collection/Conscious Aging,
               /Users/jdoe/Documents/Ram Dass Audio Collection/Cultivating the Heart of Compassion, /Users/jdoe/Documents/Cheatsheets/YAML Ain't
               Markup Language_files}

推荐阅读