在Powershell中列出给定深度或低于给定深度的文件夹

问题描述 投票:2回答:2

我有一个包含很多文件夹的目录。我想列出超过2个级别的所有文件夹(路径)。所以在下面的案例文件夹1和2中。

Directory/folder1
Directory/folder1/test1/test/testsub
Directory/folder1/test2
Directory/folder1/test3
Directory/folder2/blablabla/bla/1
Directory/folder3/test
Directory/folder4/test
Directory/folder5/test

我正在尝试以下方法:

$Depth = 3
$Path = "."

$Levels = "\*" * $Depth
$Folder = Get-Item $Path
$FolderFullName = $Folder.FullName
Resolve-Path $FolderFullName$Levels | Get-Item | ? {$_.PsIsContainer} | Write-Host
powershell recursion depth directory-structure
2个回答
1
投票

下面的解决方案(基于您自己构建)假定您的目的是找到子树超过给定深度的子目录。

如果您想要查找给定深度或更深的所有目录路径,请参阅底部部分。 您的方法无法实现这一点,因为它只在给定深度找到目录,而不是在下面。


您自己聪明的基于通配符的方法原则上应该起作用,但是:

  • (a)可以大大简化。
  • (b)需要进一步的工作来将输出限制在子树太深的子文件夹的不同列表中。

(a) Streamlining your approach:

$Depth = 3
$Path = '.'

$Levels = '/*' * $Depth
Get-ChildItem -Directory $Path/$Levels
  • 与您自己的方法一样,'/*' * $Depth动态创建一个多目录级通配符表达式(例如,/*/*$Depth2),可以附加到输入$Path以仅匹配该级别的路径。
  • -Directory开关(PSv3 +)仅限制与目录的匹配。

(b) Limiting output to the distinct set of top-level folder with too-deep subtrees:

$Depth = 3
$Path = '.'

$Levels = '/*' * $Depth
Get-ChildItem -Directory $Path/$Levels |
  ForEach-Object { ($_.FullName -split '[\\/]')[-$Depth] } |
    Select-Object -Unique

注意:由[/\\]拆分 - 也就是说,通过/\ - 使解决方案也可以在类Unix平台上运行(PowerShell Core);在Windows上,-split '\\'(逃脱的\)就足够了。

使用样本文件夹层次结构,上面会产生:

folder1
folder2
  • 如果您想要完整路径,请追加 | Convert-Path -LiteralPath { "$Path/$_" }
  • 如果你想要目录信息对象([System.IO.DirectoryInfo]),请追加 | Get-Item -LiteralPath { "$Path/$_" }

Optional reading: Getting folders up to, at, or beyond a certain depth:

注意:

  • 即使目标文件夹(目录)下面的解决方案,您也可以通过简单地省略-Directory或仅通过用-Directory替换-File来定位文件来包含文件。
  • 为简单起见,命令隐式地以当前目录为目标。

在给定深度的逻辑:

这与上述解决方案中采用的逻辑相同;以下代码仅列出深度为2的文件夹,即孙子级别的文件夹(子目录的子目录) - 请注意,与Get-ChildItem -Depth不同,深度计数以1开头,即1指的是子目录:

$depth = 2 # grandchild directories only

Get-ChildItem -Directory -Path ('*/' * $depth)
  • 要输出完整路径,请将Get-ChildItem命令括在(...).FullName中或将其传递给Select-Object -ExpandProperty FullName
  • 要输出相对路径(例如,folder1/test1/test/testsub),需要额外的工作,因为在这种情况下添加-Name将无法按预期工作(它将仅输出目录名称):
$depth = 2 # grandchild directories

# Calculate the length of the path prefix for determining relative paths.
# (Using the current dir ($PWD) as the reference path here.)
$PrefixLen = (Convert-Path -LiteralPath $PWD).Length + 1

$Levels = '/*' * $Depth
Get-ChildItem -Directory -Path ('*/' * $depth) |
  ForEach-Object { $_.FullName.Substring($PrefixLen) }

最新的逻辑:

PSv5 + -Depth参数限制Get-ChildItem的递归深度,即,它只查找达到指定深度的项目,但请注意它是深度0,而不是代表直接子项的1。 请注意,使用-Depth意味着-Recurse,尽管您也可以指定后者。

例如,要枚举当前目录中的子文件夹和孙子文件夹(2级),请使用:

$depth = 2 # child and grandchild directories

Get-ChildItem -Directory -Depth ($depth - 1)
  • 要输出完整路径,请将Get-ChildItem命令括在(...).FullName中或将其传递给Select-Object -ExpandProperty FullName
  • 要输出相对路径,只需将-Name开关添加到Get-ChildItem调用。

给定的深度或更深的逻辑:

将结果限制为大于或等于给定深度的项目需要自定义解决方案:

$depth = 2 # grandchild directories and below

Get-ChildItem -Directory -Name -Recurse |
  Where-Object { ($_ -split '[/\\]').Count -ge 2 } |
    Get-Item -LiteralPath { "$PWD/$_" }

如果您的输入路径不是(隐含的)当前目录,请将该路径替换为$PWD

  • 要输出完整路径,请将Get-Item替换为Convert-Path
  • 要输出相对路径,只需省略Get-Item调用。

-1
投票

请试试这个

$Folders = Get-ChildItem 'C:\Program Files' -Directory -Recurse -Depth 1 | 
     Select-Object -ExpandProperty fullname | 
     Sort-Object
$Folders
© www.soinside.com 2019 - 2024. All rights reserved.