Skip to content

Objects and the Pipeline

Scope: the object model — Get-Member, filtering, sorting, selecting, and formatting. The heart of PowerShell. All examples were run with PowerShell 7.5.

Get-Member: what am I holding?

Get-Process | Get-Member

Get-Member lists an object's properties and methods. When a command's output confuses you, pipe it here first. Narrow it:

Get-Process | Get-Member -MemberType Property

Where-Object: filtering

Get-Process | Where-Object { $_.CPU -gt 10 }

Where-Object keeps objects where the block is true; $_ is the current object. (The ? alias exists — prefer the full name in scripts.)

Select-Object: choosing properties

Get-Process | Select-Object Name, CPU, Id -First 5

Pick properties, take the first/last N, or compute new ones:

Get-ChildItem | Select-Object Name,
    @{ Name = "KB"; Expression = { [math]::Round($_.Length / 1KB, 1) } }

The @{ Name=...; Expression=... } hashtable builds a calculated property — derived columns on the fly.

Sort-Object and friends

Get-Process | Sort-Object CPU -Descending | Select-Object -First 5
Get-ChildItem | Measure-Object Length -Sum
Get-Service | Group-Object Status

Measure-Object aggregates (count/sum/average), Group-Object buckets by property value.

ForEach-Object: acting on each

Get-Service | Where-Object Status -eq "Stopped" |
    ForEach-Object { Start-Service $_.Name }

(Where-Object Status -eq "Stopped" is the simplified syntax — property, operator, value, no braces needed.)

Format vs data: the critical distinction

Get-Process | Format-Table Name, CPU -AutoSize   # for HUMANS
Get-Process | Select-Object Name, CPU            # for the PIPELINE

Format-* cmdlets destroy the objects — output is formatting instructions, not data. Golden rule: Format-Table (and friends) go last, only for screen display. Never pipe from a Format-* command into anything expecting data.

Exporting: objects out to the world

Get-Process | Export-Csv processes.csv -NoTypeInformation
Get-Process | ConvertTo-Json | Out-File processes.json
Import-Csv processes.csv | Where-Object { $_.CPU -gt 10 }

Export-Csv / Import-Csv round-trip through spreadsheets; ConvertTo-Json / ConvertFrom-Json through APIs and config. -NoTypeInformation keeps the CSV clean.

The pipeline, summarized

Get-ChildItem -Recurse -File |
    Where-Object { $_.Length -gt 1MB } |
    Sort-Object Length -Descending |
    Select-Object FullName,
        @{ Name = "MB"; Expression = { [math]::Round($_.Length / 1MB, 1) } } |
    Format-Table -AutoSize

Find big files, biggest first, as a readable table. Every stage passes objects; only the final Format-Table is for eyes.

Check

  • [ ] You reach for Get-Member when output confuses you
  • [ ] You can filter, sort, select, and compute a property
  • [ ] You can explain why Format-Table must come last

Next: Modules.