Overview

12 Filtering and comparisons

PowerShell provides two complementary ways to narrow results: asking the source cmdlet to return only what you want, and post-filtering objects that flow through the pipeline. The preferred approach—“filter left”—puts criteria as early as possible, ideally in the first cmdlet (for example, using a name or path parameter with wildcards). Early filtering reduces work, speeds execution, and can minimize data sent over the network. When a cmdlet can’t filter on the property you need, you switch to Where-Object to remove unwanted items after retrieval.

Filtering relies on comparison operators that evaluate to True or False. PowerShell includes numeric and date operators (-eq, -ne, -gt, -lt, -ge, -le), string operators that are case-insensitive by default with case-sensitive variants (-ceq, -cgt, and so on), logical operators (-and, -or, -not), and text-oriented operators like -like (wildcards) and -match (regular expressions). Where-Object evaluates each incoming object, exposes it as $_, and keeps only those for which the comparison is True. Because formatted column headers don’t always match real property names, you use Get-Member to discover the properties to compare. PowerShell also offers a simplified Where-Object syntax for single comparisons, but the full script-block form remains essential for multi-condition logic.

The chapter advocates an iterative command-line workflow: build a pipeline step by step, validate each stage, and refine. A worked example measures the total virtual memory of the 10 most memory-hungry processes excluding PowerShell itself by chaining Get-Process, a Where-Object filter on Name, Sort-Object on VM, Select-Object -First 10, and Measure-Object -Sum. Common pitfalls include forgetting to filter as far left and as close to the data source as possible (for remote data, filter remotely), misunderstanding where $_ is valid (especially inside nested pipelines and parentheses), and confusing formatted headers with actual property names. With these practices, you can combine a few core cmdlets to craft precise, efficient results across Windows, Linux, and macOS.

 Lab answers

  1. Get-Command -Module PSReadLine
  2. Get-Command Get-* -Module PSReadLine
  3. Get-ChildItem /usr/bin/* | Where-Object {$_.length –gt 5MB}
  4. Find-Module -Name PS* | Where-Object {$_.Author -like 'Microsoft*'}
  5. Get-ChildItem | where-object LastWriteTime -ge (get-date).AddDays(-7)
  6. Get-Process -Name pwsh,bash

FAQ

What are the two ways to filter results in PowerShell, and which one should I prefer?The two approaches are: (1) ask the first cmdlet to return only what you need (filter left), for example Get-Process -Name p*,*s* or Get-ChildItem -Path *.log; and (2) retrieve a broader set and then pare it down with Where-Object. Prefer filter left because it reduces work and data early.
What does “filter left” mean, and what are its trade-offs?“Filter left” means place your filtering criteria as early (left) in the pipeline as possible—ideally in the first cmdlet. Benefits: faster, less memory/CPU, less network traffic for remote data. Trade-offs: each cmdlet has different (and sometimes limited) filter parameters (for example, Get-Process can filter by Name or Id only).
When should I use Where-Object, and how does it work?Use Where-Object when the first cmdlet can’t express the filter you need. It evaluates each input object using a script block; if the expression is True, that object continues in the pipeline. Example: Get-Process | Where-Object { $_.WorkingSet -gt 100MB } keeps only processes using more than 100 MB of working set memory.
Which comparison and logical operators are most important to know?Key comparison operators: -eq, -ne, -gt, -lt, -ge, -le. String comparisons are case-insensitive by default; use case-sensitive variants like -ceq, -cgt, etc. Combine tests with -and, -or, and invert with -not (or !). Examples: 10 -gt 5 is True; -not $proc.Responding checks for “not responding.”
What’s the difference between -like and -match?-like uses wildcard patterns (*, ?, []) and is great for simple name/pattern checks, e.g., "Hello" -like "*ll*". -match uses regular expressions for more complex patterns. Both are case-insensitive by default; use -clike/-cmatch for case-sensitive comparisons.
Where can I use the $_ automatic variable, and what are common pitfalls?$_ represents the current pipeline object and is valid only within script blocks where PowerShell expects it (e.g., Where-Object, ForEach-Object). Be careful with nested pipelines in parentheses; $_ refers to the innermost pipeline’s current object. Walk through nested commands step by step to avoid confusion.
What is the simplified Where-Object syntax, and when should I use it?PowerShell supports a shorthand for single comparisons: Get-Process | Where-Object WorkingSet -gt 100MB. It’s easy to read, but it only supports one comparison. For multiple conditions, use the full script block: Where-Object { $_.WorkingSet -gt 100MB -and $_.CPU -gt 100 }.
How do I build a pipeline to sort, take the top N, and sum a property?Iterate in steps: get data, filter, sort, select, then measure. Example: Get-Process | Where-Object { $_.Name -notlike 'pwsh*' } | Sort-Object VM -Descending | Select-Object -First 10 | Measure-Object -Property VM -Sum. Use -First/-Last in Select-Object and Measure-Object -Sum to aggregate.
Why don’t the output column headers always match property names, and how do I find the right properties?Formatting can show “friendly” headers that differ from actual property names. Use Get-Member to discover real properties. For example, the column header PM(MB) corresponds to the property PM. Don’t rely on formatted output to infer property names.
How do I apply “filter left” when working with remote data?Filter as close to the data source as possible. Use remoting so the remote machine does the filtering, reducing data sent over the network. Example: Invoke-Command -ComputerName srv1 -ScriptBlock { Get-Process | Where-Object { $_.WorkingSet -gt 100MB } }.

pro $24.99 per month

  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose one free eBook per month to keep
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime

lite $19.99 per month

  • access to all Manning books, including MEAPs!

team

5, 10 or 20 seats+ for your team - learn more


choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • Learn PowerShell in a Month of Lunches, Fourth Edition ebook for free
choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • Learn PowerShell in a Month of Lunches, Fourth Edition ebook for free
choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • Learn PowerShell in a Month of Lunches, Fourth Edition ebook for free