Filtering & Shaping the Pipeline
25 minMaster Where-Object, Select-Object, Sort-Object, Measure-Object, and ForEach-Object to slice, sort, and summarise live system data.
- ▸Filter objects with Where-Object using both the scriptblock and simplified forms
- ▸Apply comparison operators (-eq, -ne, -gt, -like, -match) and combine them with -and / -or
- ▸Shape output with Select-Object (properties, -First/-Last, calculated columns)
- ▸Sort results with Sort-Object and summarise with Measure-Object
- ▸Iterate objects inline with ForEach-Object and the $_ automatic variable
The Pipeline Is a Conveyor Belt
When you run Get-Service PowerShell doesn't hand you a block of text — it hands you a stream of objects, one per service. Every cmdlet to the right of a pipe (|) receives those objects and can inspect, filter, or transform them.
Where-Object — Keep Only What You Need
Two forms, same result:
# Simplified form (one property, one operator)
Get-Service | Where-Object Status -eq 'Running'
# Scriptblock form (required for -and / -or or complex logic)
Get-Service | Where-Object { $_.Status -eq 'Running' -and $_.StartType -eq 'Automatic' }
$_ is the current object in the pipeline — think of it as "this one".
Comparison Operators
| Operator | Meaning |
|---|---|
-eq / -ne | equals / not equals |
-gt / -lt | greater / less than |
-ge / -le | greater-or-equal / less-or-equal |
-like | wildcard match (*, ?) |
-match | regex match |
Combine with -and and -or inside a scriptblock:
Get-Process | Where-Object { $_.CPU -gt 10 -and $_.WorkingSet -gt 100MB }
Select-Object — Choose Your Columns
# Pick specific properties
Get-Service | Select-Object Name, Status, StartType
# First / last N objects
Get-Process | Sort-Object CPU -Descending | Select-Object -First 5
# Calculated property
Get-Process | Select-Object Name, @{Name='MemMB'; Expression={ [math]::Round($_.WorkingSet / 1MB, 1) }}
The hashtable @{Name='...'; Expression={...}} lets you rename or compute a column on the fly.
Sort-Object
Get-Process | Sort-Object -Property CPU -Descending
Get-Service | Sort-Object DisplayName # ascending by default
Measure-Object — Count and Aggregate
Get-Service | Where-Object Status -eq 'Running' | Measure-Object
# Count : 87
Get-Process | Measure-Object WorkingSet -Sum -Average
ForEach-Object — Act on Each in Turn
Get-Service | Where-Object Status -eq 'Stopped' | ForEach-Object {
Write-Host "Stopped service: $($_.DisplayName)"
}
Use ForEach-Object when you need to do something for every object rather than just display it.
Quick check
In this lab you will work through a realistic ops workflow: find stopped services, identify the greediest processes, count and sum resources, emit a formatted report line per process, and finally build a tidy calculated-property table — all using a single pipeline per step. The outputs shown are representative; exact numbers will differ on your system.
Use Where-Object to list only the services that are currently stopped and have a StartType of Automatic — the classic misconfiguration hunt. Use the scriptblock form so you can combine two conditions with -and.
Get-Service | Where-Object { $_.Status -eq 'Stopped' -and $_.StartType -eq 'Automatic' }