Skip to content
AgileLogics
4 min read

Filtering with Where-Object

Prerequisites: The pipeline

Where-Object keeps only the objects that match a condition.

Two syntaxes

$products = @(
  [pscustomobject]@{ Name = 'Keyboard';   Category = 'Accessories'; Price = 89 }
  [pscustomobject]@{ Name = 'USB-C Hub';  Category = 'Accessories'; Price = 35.5 }
  [pscustomobject]@{ Name = 'Monitor';    Category = 'Displays';    Price = 249.99 }
  [pscustomobject]@{ Name = 'Headphones'; Category = 'Audio';       Price = 199 }
)

# Simple syntax: one condition
$products | Where-Object Price -gt 100 | Select-Object -ExpandProperty Name

# Script block syntax: any expression, using $_
$products | Where-Object { $_.Category -eq 'Accessories' -and $_.Price -lt 50 } |
  Select-Object -ExpandProperty Name
Monitor
Headphones
USB-C Hub
  • The simple form (Where-Object Property -operator Value) reads well for a single condition.
  • The script block form handles combined conditions with -and, -or, and -not.

Filtering by pattern

$files = 'report.pdf', 'photo.jpg', 'notes.txt', 'report-old.pdf', 'logo.png'

$files | Where-Object { $_ -like '*.pdf' }
'---'
$files | Where-Object { $_ -match '^(photo|logo)\.' }
report.pdf
report-old.pdf
---
photo.jpg
logo.png

-like uses wildcards; -match uses regular expressions (both covered in the Operators lesson).

Filter early — "filter left"

Many commands can filter themselves, which is much faster than getting everything and then using Where-Object:

# illustrative
# Slower: gets every file, then filters
Get-ChildItem -Recurse | Where-Object Extension -eq '.log'

# Faster: the file system does the filtering
Get-ChildItem -Recurse -Filter *.log

Use a command's own parameters (-Filter, -Name, -Include) when they exist, and Where-Object for everything else.

Practice

From the products above, list the names of products that are not in the Accessories category.

Show solution
$products = @(
  [pscustomobject]@{ Name = 'Keyboard';   Category = 'Accessories' }
  [pscustomobject]@{ Name = 'Monitor';    Category = 'Displays' }
  [pscustomobject]@{ Name = 'Headphones'; Category = 'Audio' }
)
$products | Where-Object Category -ne 'Accessories' | Select-Object -ExpandProperty Name
Monitor
Headphones