对管道中的每个对象执行脚本块,用于转换、批量操作和带状态的遍历。
ForEach-Object 逐个接收管道对象,对每个对象运行 -Process 脚本块,输出脚本块写出的任何内容;别名是 foreach 和 %。-Begin 在第一个对象前执行一次,-End 在全部对象后执行一次,适合计数、汇总和打开/关闭资源;-MemberName 可直接调用属性或方法。
管道:-InputObject 按值接收对象,也是该命令的主要输入方式;脚本块内用 $_(或 $PSItem)引用当前对象。权限:命令本身不需要权限,脚本块里的操作按目标资源的 ACL 判断。边界:它负责“对每个对象做事”,筛选用 Where-Object,选列用 Select-Object;foreach 关键字适合内存集合和需要 break/continue 的循环。
版本:5.1 没有并行参数,循环是串行执行;7.x 差异:提供 -Parallel 和 -ThrottleLimit,在独立运行空间中并发执行,变量必须用 $using: 传入,输出顺序不保证。
# 1. 对数字序列逐个计算,验证脚本块输入输出
PS C:\> 1..5 | ForEach-Object { $_ * 2 }
# 2. 把文件对象转换成自定义结果,保留需要的字段
PS C:\> Get-ChildItem C:\Logs -File | ForEach-Object { [pscustomobject]@{ Name=$_.Name; KB=[math]::Round($_.Length/1KB,1) } }
# 3. 用 Begin/Process/End 统计行数,只输出一次汇总
PS C:\> Get-Content C:\Logs\app.log | ForEach-Object -Begin { $i=0 } -Process { $i++ } -End { "total=$i" }
# 4. 对每个匹配进程取 Id,供后续精确操作
PS C:\> Get-Process -Name chrome -ErrorAction SilentlyContinue | ForEach-Object { $_.Id }
# 5. 7.x 差异:并行处理,用 $using: 传入父作用域变量
PS C:\> $root = 'C:\Temp'; 1..3 | ForEach-Object -Parallel { Join-Path $using:root $_ } -ThrottleLimit 2
# 6. 对每个文件执行检查,并用 -ErrorAction Stop 暴露首个错误
PS C:\> Get-ChildItem C:\Data -File | ForEach-Object { Get-Content $_.FullName -TotalCount 1 -ErrorAction Stop }
ForEach-Object 时内层 $_ 覆盖外层;在进入内层前把外层对象存到变量,例如 $outer = $_。return 只会结束当前对象的这一轮,后续对象继续处理;要终止整个管道应重构逻辑或用 foreach 关键字。-Parallel 在独立运行空间中执行,普通变量不可见,必须 $using:;输出顺序不保证,且不适合共享同一文件/连接而不加锁。-Parallel 不是给 I/O 轻任务无条件加速的;运行空间有启动成本,小集合串行更快,并发度用 -ThrottleLimit 控制。+= 在循环里累加数组是 O(n²) 且会复制对象;让脚本块直接输出,或使用 List[object]。-ErrorAction Stop 或在块内 throw。foreach 关键字与 ForEach-Object 别名同名但语义不同:关键字支持 break/continue,管道版本是流式处理,不能同样中断。Where-Object — 在遍历前筛选对象。Select-Object — 选择属性或截取前 N 条。Sort-Object — 对结果排序。PowerShell — 了解 5.1 与 7.x 的语法差异。合上页面,先回答,再展开对照。
ForEach-Object 脚本块里的 return 会终止整个管道吗?-Parallel 为什么不能直接读父作用域的普通变量?foreach 关键字和 ForEach-Object 各适合什么场景?$using: 显式传入父作用域变量。break/continue 的循环;cmdlet 适合流式管道处理。
小程序版
微信扫码,随时查命令