在 Powershell 中列出给定深度或以下的文件夹

Nic*_*ick 5 powershell recursion directory-structure depth

我有一个包含很多文件夹的目录。我想列出所有深度超过 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
Run Code Online (Sandbox Code Playgroud)

我正在尝试以下操作:

$Depth = 3
$Path = "."

$Levels = "\*" * $Depth
$Folder = Get-Item $Path
$FolderFullName = $Folder.FullName
Resolve-Path $FolderFullName$Levels | Get-Item | ? {$_.PsIsContainer} | Write-Host
Run Code Online (Sandbox Code Playgroud)

mkl*_*nt0 7

下面的解决方案是您自己构建的,假设您的意图是查找子树超过给定深度的子目录

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


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

  • (a) 可以大大简化。

  • (b) 需要进行额外的工作来将输出限制为子树太深的子文件夹的不同列表。

(a) 简化您的方法:

$Depth = 3
$Path = '.'

$Levels = '/*' * $Depth
Get-ChildItem -Directory $Path/$Levels
Run Code Online (Sandbox Code Playgroud)
  • 正如您自己的方法一样,'/*' * $Depth动态创建一个多目录级别通配符表达式(例如,/*/*对于 a $Depthof 2),可以将其附加到输入$Path以仅匹配该级别的路径。

  • 开关-Directory(PSv3+) 仅限制匹配目录。

(b) 将输出限制为具有太深子树的不同顶级文件夹集:

$Depth = 3
$Path = '.'

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

注意:分割[/\\]- 即按/\- 使解决方案也可以在类 Unix 平台上工作(PowerShell Core);在 Windows 上,-split '\\'(通过转义\)就足够了。

使用您的示例文件夹层次结构,上面的内容将产生:

folder1
folder2
Run Code Online (Sandbox Code Playgroud)
  • 如果您想要完整路径,请附加
    | Convert-Path -LiteralPath { "$Path/$_" }.

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


可选阅读:使文件夹达到、达到或超过一定深度:

笔记:

  • 即使下面的解决方案以文件夹(目录)为目标,您也可以通过简单地省略 来包含文件-Directory,或者仅通过替换-Directory为 来包含文件-File

  • 为简单起见,这些命令隐式定位当前目录。


仅在给定深度的逻辑:

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

$depth = 2 # grandchild directories only

Get-ChildItem -Directory -Path ('*/' * $depth)
Run Code Online (Sandbox Code Playgroud)
  • 要输出完整路径,请将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) }
Run Code Online (Sandbox Code Playgroud)

达到给定深度的逻辑:

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

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

$depth = 2 # child and grandchild directories

Get-ChildItem -Directory -Depth ($depth - 1)
Run Code Online (Sandbox Code Playgroud)
  • 要输出完整路径,请将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/$_" }
Run Code Online (Sandbox Code Playgroud)

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

  • 要输出完整路径,请替换Get-ItemConvert-Path.

  • 要输出相对路径,只需省略调用即可Get-Item