PowerShell Genie
Learn Filtering with Where-Object

Filtering with Where-Object

Most PowerShell commands return more than you need. Where-Object keeps only the objects that pass your test — it's the funnel most working pipelines run through.

Beginner 4 min read Works in Windows PowerShell 5.1 and PowerShell 7

Documentation: Microsoft Learn — PowerShell reference

What Where-Object does

Where-Object sits in the middle of a pipeline and tests each object, one at a time. If the test is true, the object passes through. If not, it's dropped. Nothing is changed — filtering only decides what survives.

1PS> Get-Service | Where-Object Status -eq 'Stopped'

Five service objects go in. Each one is asked: "is your Status equal to 'Stopped'?" Two answer yes — Spooler and WinRM. Those two come out.

Genie tip: read the pipeline out loud — "get the services, where the status equals stopped." If you can say it, you can write it.

See the objects move

Inspect this authored example with fictional data in the bounded browser model. The numbered stages show how its objects change.

Get-Service | Where-Object Status -eq 'Stopped'
  1. Stage 1Get-ServicePositional values or no named parameters
  2. Stage 2Where-Object-eq

    The filter script block

    For anything beyond a simple comparison, the test lives in a script block — the curly braces. Inside it, $_ means the object being tested right now:

    1PS> Get-Process | Where-Object { $_.WorkingSet64 -gt 500MB }

    The comparison operators you'll reach for daily:

    • -eq / -ne — equal / not equal
    • -gt / -lt / -ge / -le — greater / less than (and "or equal")
    • -like — wildcard match ('Win*'), -match — regex match

    You only need -eq today — the rest are here when you're ready for them.

    Combine tests with -and and -or (the sample lab below runs -and chains; -or works the same way in real PowerShell). And check the property name first with Get-Service | Get-Member — by default (Strict Mode aside), a misspelled property never errors, it just silently matches nothing.

    Version note: the short form (Where-Object Status -eq 'Stopped') needs PowerShell 3.0+. The script-block form works everywhere, including 5.1 and 7.x.

    Try it: filter services

    Safe to try — this lesson only reads, never changes, and nothing leaves your browser

    Keep stopped services whose names start with "Win". Two conditions, one filter:

    1PS> Get-Service | Where-Object { $_.Status -eq 'Stopped' -and $_.Name -like 'Win*' }

    Sample output · fictional data, shaped like the real thing

    Result 1 object returned
    StatusNameDisplayName
    StoppedWinRMWindows Remote Management (WS-Management)

    Common mistakes

    Using = instead of -eq. A single = assigns. On services it errors out loudly — Status is read-only on ServiceController, so Where-Object { $_.Status = 'Stopped' } fails instead of filtering. The silent version of this trap lives on objects with settable properties:

    1PS> $apps = [pscustomobject]@{ Name = 'Backup'; Enabled = $false }
    2PS> $apps | Where-Object { $_.Enabled = $true } # assigns $true — returns no objects

    The lesson above builds a pretend object. This bounded demo models the same assignment on fictional user objects with writable properties. Toggle it and inspect the result:

    Interactive simulation · fictional data

    [pscustomobject]@{...} just builds a pretend object to demonstrate on — you'll build these properly in the Script stage.

    That filter returns no objects: the ungrouped assignment changes each writable Enabled property to $true but outputs no value for Where-Object to test. The original objects are still changed, even though the pipeline result is empty. Parentheses change the behavior: Where-Object { ($_.Enabled = $true) } outputs the assigned Boolean and keeps every object. To compare without changing objects, use -eq (case-insensitive by default; -ceq when case matters). See Microsoft’s grouping assignment statements reference.

    Filtering on a property that doesn't exist. Where-Object State -eq 'Running' on services returns nothing, with no error — the property is called Status, not State. When a filter returns nothing, suspect the property name first.

    Genie tip: an empty result is a clue, not a failure. Run the command without the filter first, look at the actual property names, then add Where-Object back.

    Your turn

    On your own machine, list the running services whose names start with the letter "S". Write it before you peek.

    Check it here first. Type your command and run it against sample data before trying your own machine:

    Interactive simulation · fictional data

    Checked against fictional sample data — on your machine the service names will differ, but the shape of the answer is the same.

    Prove it: write it alone

    Blank editor. No starter, no hints. Write a command that returns only the stopped services from the five-service sample:

    Interactive simulation · fictional data

    Practise this

    Filter stopped services

    Return the complete records for stopped services.

    Review the lesson

    Recap

    Where-Object tests each object in the pipeline and keeps only the ones whose test is true. = assigns (and lies silently on settable properties) — compare with -eq, case-insensitive by default. When a filter returns nothing, suspect the property name first.

    When this lesson is done, you can write from a blank prompt: Get-Service | Where-Object Status -eq 'Stopped'

    Next: Select-Object reference — choose the properties to keep

    This lesson counts as done when you can write the filter from a blank prompt — solve it alone above to unlock the route.

    Genie guideFiltering with Where-Object

    Most PowerShell commands return more than you need. Where-Object keeps only the objects that pass your test — it's the funnel most working pipelines run through.

    Stuck? Re-read the section, then try the filter yourself.