The Pipeline
Master PowerShell's pipeline to chain commands together, filter data, sort results, and transform output. Learn how object-based piping works.
What is the Pipeline?
The pipeline is PowerShell's most powerful feature. It lets you chain commands together using the pipe symbol (|), where the output of one command becomes the input of the next.
# Basic pipeline: Get processes, then sort by CPU usage
Get-Process | Sort-Object CPU -DescendingUnlike Bash (which pipes text), PowerShell pipes objects. This means you have access to structured properties and methods at every stage.
How the Pipeline Works
# Step by step:
# 1. Get-Process returns process OBJECTS
# 2. Objects flow through the pipe |
# 3. Sort-Object receives those objects and sorts them
# 4. Select-Object picks specific properties to display
Get-Process | Sort-Object CPU -Descending | Select-Object -First 10 Name, CPU, WorkingSetThink of it as an assembly line:
[Get Data] → | → [Filter] → | → [Sort] → | → [Format] → | → [Output]
Essential Pipeline Cmdlets
Where-Object — Filtering
Filter objects based on conditions:
# Get processes using more than 100MB of memory
Get-Process | Where-Object { $_.WorkingSet -gt 100MB }
# Get running services
Get-Service | Where-Object { $_.Status -eq "Running" }
# Get large files
Get-ChildItem -Recurse | Where-Object { $_.Length -gt 1MB }
# Simplified syntax (PowerShell 3+)
Get-Service | Where-Object Status -eq "Running"
# Multiple conditions
Get-Process | Where-Object { $_.CPU -gt 10 -and $_.WorkingSet -gt 50MB }The $_ variable represents the current object in the pipeline (also available as $PSItem).
Select-Object — Choosing Properties
Select specific properties or a subset of results:
# Select specific properties
Get-Process | Select-Object Name, CPU, WorkingSet, Id
# Select first/last N items
Get-Process | Sort-Object CPU -Descending | Select-Object -First 5
Get-Process | Sort-Object CPU -Descending | Select-Object -Last 3
# Create calculated properties
Get-Process | Select-Object Name, @{
Name = "MemoryMB"
Expression = { [math]::Round($_.WorkingSet / 1MB, 2) }
}
# Select unique values
Get-Process | Select-Object Name -Unique
# Expand a single property to get raw values
Get-Process | Select-Object -ExpandProperty NameSort-Object — Sorting
# Sort ascending (default)
Get-Process | Sort-Object Name
# Sort descending
Get-Process | Sort-Object CPU -Descending
# Sort by multiple properties
Get-ChildItem | Sort-Object Extension, Name
# Sort unique values
1, 3, 2, 3, 1, 5 | Sort-Object -UniqueForEach-Object — Iterating
Execute an action on each object:
# Simple iteration
1..10 | ForEach-Object { $_ * 2 }
# Process each file
Get-ChildItem *.txt | ForEach-Object {
Write-Host "Processing: $($_.Name)"
Get-Content $_.FullName | Measure-Object -Line
}
# Simplified syntax
Get-Process | ForEach-Object Name
# Using method syntax
"hello", "world" | ForEach-Object ToUpperGroup-Object — Grouping
# Group processes by name
Get-Process | Group-Object Name | Sort-Object Count -Descending
# Group files by extension
Get-ChildItem -Recurse | Group-Object Extension | Sort-Object Count -Descending
# Group services by status
Get-Service | Group-Object StatusMeasure-Object — Statistics
# Count items
Get-Process | Measure-Object
# Get statistics on a property
Get-Process | Measure-Object CPU -Sum -Average -Maximum -Minimum
# Count lines, words, characters in a file
Get-Content "file.txt" | Measure-Object -Line -Word -CharacterPipeline Output
Format-Table and Format-List
# Table format (default for many commands)
Get-Process | Format-Table Name, CPU, WorkingSet -AutoSize
# List format (shows all properties vertically)
Get-Process -Name "pwsh" | Format-List *
# Custom column widths
Get-Service | Format-Table @{
Label = "Service Name"
Expression = { $_.Name }
Width = 30
}, Status -AutoSizeExporting Data
# Export to CSV
Get-Process | Select-Object Name, CPU, WorkingSet |
Export-Csv -Path "processes.csv" -NoTypeInformation
# Export to JSON
Get-Service | ConvertTo-Json | Out-File "services.json"
# Export to HTML
Get-Process | Select-Object Name, CPU, WorkingSet |
ConvertTo-Html -Title "Process Report" |
Out-File "report.html"
# Export to XML
Get-Process | Export-Clixml "processes.xml"Redirecting Output
# Send to file (overwrite)
Get-Process | Out-File "processes.txt"
# Append to file
Get-Process | Out-File "processes.txt" -Append
# Send to clipboard
Get-Process | Select-Object Name | Set-Clipboard
# Suppress output
Get-Process | Out-Null
# Display in grid view (Windows only)
Get-Process | Out-GridViewAdvanced Pipeline Techniques
Tee-Object — Split the Pipeline
Send output to both a file and the next command:
Get-Process | Tee-Object -FilePath "all-processes.txt" |
Where-Object CPU -gt 10 |
Select-Object Name, CPUCompare-Object — Comparing
# Compare two arrays
$before = Get-Process
# ... do something ...
$after = Get-Process
Compare-Object $before $after -Property NamePipeline with Where and ForEach
# Real-world example: Find large log files and get their sizes
Get-ChildItem -Path "C:\Logs" -Filter "*.log" -Recurse |
Where-Object { $_.Length -gt 10MB } |
Sort-Object Length -Descending |
ForEach-Object {
[PSCustomObject]@{
Name = $_.Name
SizeMB = [math]::Round($_.Length / 1MB, 2)
Modified = $_.LastWriteTime
Path = $_.DirectoryName
}
} |
Format-Table -AutoSizePipeline Performance Tips
# GOOD: Filter early (left-side filtering)
Get-ChildItem -Path "C:\" -Filter "*.log" -Recurse
# BAD: Filter late (processes all files first)
Get-ChildItem -Path "C:\" -Recurse | Where-Object Extension -eq ".log"
# GOOD: Use cmdlet parameters instead of Where-Object when possible
Get-Process -Name "chrome"
# BAD: Gets all processes then filters
Get-Process | Where-Object Name -eq "chrome"Rule of thumb: Filter as far LEFT (early) in the pipeline as possible. Use cmdlet parameters for filtering before resorting to
Where-Object.
Exercises
- List the 10 processes consuming the most memory, showing only Name and MemoryMB
- Find all
.txtfiles in your Documents folder and count them - Group running services by their StartType and count each group
- Export a list of all environment variables to a CSV file
- Create a pipeline that finds files modified in the last 24 hours
Next up: Variables and Data Types — learn how to store and work with data in PowerShell!