如何无需嵌套ForEach-Object即可递归遍历Job文本文件到最低层级
解决方案
你描述的无限层级嵌套遍历场景,用递归函数或者基于栈/队列的迭代遍历即可实现,无需编写多层嵌套循环,两种常用实现方案如下:
方案1:递归函数实现(最直观,适配绝大多数场景)
通过封装递归函数自动处理层级,同时新增已访问集合避免循环引用导致的死循环:
# 切换到目标目录 Set-Location "C:\Files" # 存储已遍历过的文件,避免循环引用 $visited = @{} # 定义递归打印函数 function Print-JobTree { param( [string]$FileName, [int]$Depth = 0 ) # 跳过已访问的文件防止循环 if ($visited.ContainsKey($FileName)) { return } $visited[$FileName] = $true # 按层级输出带缩进的文件名 Write-Host ("`t" * $Depth + $FileName) # 读取当前文件包含的子Job文件名 $childJobs = Get-Content $FileName -ErrorAction SilentlyContinue if ($null -eq $childJobs) { return } # 遍历子Job,深度+1递归调用 foreach ($child in $childJobs) { Print-JobTree -FileName $child.Trim() -Depth ($Depth + 1) } } # 遍历所有顶层文件启动递归 Get-ChildItem -Name | ForEach-Object { Print-JobTree -FileName $_ }
方案2:栈迭代实现(适配超深嵌套场景,避免递归栈溢出)
如果你的嵌套层级可能超过PowerShell默认递归栈上限(默认是几百到上千层),可以用基于栈的非递归方案:
Set-Location "C:\Files" $visited = @{} # 栈中存储 文件名+当前深度 的结构 $stack = [System.Collections.Generic.Stack[PSObject]]::new() # 先把所有顶层文件压入栈,注意倒序压入保证输出顺序和目录顺序一致 $topFiles = Get-ChildItem -Name for ($i = $topFiles.Count - 1; $i -ge 0; $i--) { $stack.Push(@{FileName = $topFiles[$i]; Depth = 0}) } while ($stack.Count -gt 0) { $current = $stack.Pop() $fileName = $current.FileName $depth = $current.Depth if ($visited.ContainsKey($fileName)) { continue } $visited[$fileName] = $true Write-Host ("`t" * $depth + $fileName) # 读取子Job,倒序压入栈保证输出顺序和文件内顺序一致 $childJobs = Get-Content $fileName -ErrorAction SilentlyContinue if ($null -ne $childJobs) { for ($i = $childJobs.Count - 1; $i -ge 0; $i--) { $stack.Push(@{FileName = $childJobs[$i].Trim(); Depth = $depth + 1}) } } }
两种方案的输出效果和你给出的示例完全一致,支持任意深度的嵌套遍历,无需修改代码新增循环层。
内容的提问来源于stack exchange,提问作者arealhobo
相关产品推荐
相关产品推荐

