管道传的是对象
PowerShell 的管道与 CMD、Bash 有本质区别:上游命令把 .NET 对象逐个写进管道,下游命令直接读对象的属性与方法,而不是按行解析文本。所以 Get-Process | Where-Object CPU -gt 100 是在比较数值属性,不需要切列,也不受列宽或空格数量影响。只有当对象流到达管道最末端准备显示时,格式化系统才把它渲染成表格。理解了这一层,就能解释为什么管道里能排序、能求和,也能解释为什么 Format-* 一旦出现就不该再往后接计算。
基本信息
| 适用平台 | Windows PowerShell 5.1 与 PowerShell 7 及以上,模型一致 |
|---|---|
| 核心模型 | 管道中流动的是对象,属性与方法随对象一起传递 |
| 常见环节 | 产生对象、过滤、投影、排序聚合、输出格式化 |
| 探路手段 | 用 Get-Member 查看当前管道中对象的类型与可用成员 |
| 运算符 | 比较用 -eq、-gt、-like、-match 等,与 CMD 的 == 写法无关 |
典型使用场景
- 资源排查:按 CPU、内存等属性排序取前几名,不必再看固定宽度的表格
- 批量清洗:先用 Where-Object 筛出目标对象,再交给 ForEach-Object 统一处理
- 生成报表:管道末端接 Export-Csv 或 ConvertTo-Json,直接落成结构化文件
- 计算汇总:Measure-Object 在管道里求和、求平均、计数
- 结果复用:把管道结果存入变量,后续按属性反复取用而不必重跑命令
- 编写可组合函数:函数声明接受管道输入后,就能与内置 cmdlet 混搭
管道各环节职责
| 环节类型 | 职责 | 代表命令 |
|---|---|---|
| 产生对象 | 从系统或文件读入原始数据 | Get-Process、Get-ChildItem、Import-Csv |
| 过滤筛选 | 按条件保留部分对象 | Where-Object、Select-Object -First |
| 投影派生 | 取需要的列或算出新列 | Select-Object Name, @{n='MB';e={...}} |
| 排序聚合 | 重排顺序、分组、统计 | Sort-Object、Group-Object、Measure-Object |
| 输出格式化 | 渲染成表格或写入文件 | Format-Table、Export-Csv、Out-File |
常用示例
常用示例
# 上游产生对象,下游直接按属性过滤,无需解析文本
Get-Process | Where-Object CPU -gt 100 | Select-Object Name, Id, CPU
# 按大小排序取前 5,Length 是数值属性而非字符串
Get-ChildItem $env:TEMP -File | Sort-Object Length -Descending | Select-Object -First 5 Name, Length
# 在管道里做统计
Get-ChildItem D:\Logs -File | Measure-Object Length -Sum
# 先看清对象有哪些属性,再决定取哪几列
Get-Service | Get-Member -MemberType Property
# 格式化只能放在末端,之后不要再接计算
Get-Process | Sort-Object WS -Descending | Select-Object -First 5 | Format-Table Name, WS常见对象与关键属性
| 命令 | 对象类型 | 常用属性 |
|---|---|---|
| Get-Process | System.Diagnostics.Process | Name、Id、CPU、WorkingSet64、Path |
| Get-Service | ServiceController | Name、DisplayName、Status、StartType |
| Get-ChildItem | FileInfo 与 DirectoryInfo | Name、Length、LastWriteTime、FullName |
| Get-ItemProperty | PSCustomObject(结构随来源变化) | 注册表值、文件属性等键值 |
管道是流式的:对象逐个流过各环节,不会等上游全部产完再交给下游。所以 Select-Object -First 会提前截断上游,日志里出现「管道已停止」提示多与此有关。
自定义函数想参与管道,需要给参数加 ValueFromPipeline 标记并在 process 块里处理当前对象,否则函数只能一次性接收整批输入,行为与内置 cmdlet 不一致。
与 CMD 管道的区别
- CMD 管道传的是文本行,下游只能做字符串匹配,列位置或空格一变就失效
- PowerShell 管道传对象,下游按属性名取值,输出列增减不影响逻辑
- CMD 的竖线后面只能接外部程序,PowerShell 里既能接内置 cmdlet 也能接外部程序
- 外部程序进入 PowerShell 管道时仍是纯文本,需要先解析成对象才能享受属性过滤
外部程序输出进入管道时是字符串,必须先用 ConvertFrom-Csv、ConvertFrom-Json 或正则拆解成对象,才能按属性过滤;反过来把对象交给外部程序之前,通常要先转成文本形式。