HOWTO · PowerShell

How to Use the Where-Object Command in PowerShell

Learn how Where-Object filters pipeline objects with script blocks, property conditions, aliases, and combined predicates.

On this page

Use Where-Object to keep only the objects in a PowerShell pipeline that satisfy a condition. A condition can inspect the current object with a script block, or use the cmdlet’s simplified property syntax for common comparisons. The examples below use small, fixed collections so you can adapt the predicates without depending on files or running processes on your computer.

The Where-Object Cmdlet in PowerShell

PowerShell commands commonly pass objects through a pipeline. Where-Object evaluates its condition once for each incoming object and emits an object only when the condition is true. Inside a script block, $_ refers to the current object being evaluated. This makes the cmdlet useful when a collection contains more items than the next command needs.

For example, this pipeline keeps the two records whose Status is Ready and writes their names. This is a basic pattern to adapt to your own object properties:

$tasks = @(
    [pscustomobject]@{ Name = 'Build'; Status = 'Ready' }
    [pscustomobject]@{ Name = 'Test'; Status = 'Waiting' }
    [pscustomobject]@{ Name = 'Package'; Status = 'Ready' }
)
$tasks | Where-Object { $_.Status -eq 'Ready' } | ForEach-Object { $_.Name }

Creating Filter Conditions With Script Blocks in PowerShell

A script block is code enclosed in braces. With Where-Object, it acts as a predicate: the expression is evaluated for each pipeline object, and objects with a true result pass through. You can name the script-block parameter with -FilterScript or pass the script block positionally:

$services = @(
    [pscustomobject]@{ Name = 'Archive'; StartType = 'Automatic' }
    [pscustomobject]@{ Name = 'Indexer'; StartType = 'Manual' }
)
$services | Where-Object -FilterScript { $_.StartType -eq 'Automatic' }

The positional form uses the same condition with less syntax: $services | Where-Object { $_.StartType -eq 'Automatic' }. Both forms evaluate each object as it arrives in the pipeline. Choose the named form when making the parameter role explicit helps readability; the script block remains useful for logic involving several properties or operators.

Use Where-Object to Filter Objects in PowerShell

A property predicate works with any pipeline objects that expose the property being tested. For instance, filter a fixed set of file-like records by extension as follows:

$files = @(
    [pscustomobject]@{ Name = 'notes.csv'; Extension = '.csv' }
    [pscustomobject]@{ Name = 'readme.txt'; Extension = '.txt' }
    [pscustomobject]@{ Name = 'sales.csv'; Extension = '.csv' }
)
$files | Where-Object { $_.Extension -eq '.csv' }

For real directory contents, Get-ChildItem produces file system objects, so a similar predicate is $items | Where-Object { $_.Extension -eq '.csv' } after assigning the desired directory listing to $items. The matching items depend on that directory’s contents. Where is an alias for Where-Object, so the equivalent script-block form can use Where in its place.

Creating Filter Conditions With Parameters in PowerShell

For common comparisons, simplified syntax names a property, a comparison parameter, and a value directly after Where-Object. For example, $tasks | Where-Object -Property Status -EQ 'Ready' filters by the Status property. Here, -Property and -EQ are parameters of Where-Object; parameter names are case-insensitive, so -eq names the same comparison parameter in this syntax. Inside a script block, -eq is instead the comparison operator used in expressions such as $_.Status -eq 'Ready'.

This form is concise for a single property comparison. Use a script block when a condition needs more control, such as comparing two properties or combining predicates. Both styles filter the incoming objects rather than changing them.

Using Multiple Conditional Statements

Combine conditions in a script block with -and when every condition must be true, or -or when either condition can be true. Parentheses group comparisons and make the intended logic easier to scan; they are not a special subexpression requirement.

$tasks = @(
    [pscustomobject]@{ Name = 'Build'; Status = 'Ready'; Priority = 1 }
    [pscustomobject]@{ Name = 'Test'; Status = 'Waiting'; Priority = 1 }
    [pscustomobject]@{ Name = 'Package'; Status = 'Ready'; Priority = 3 }
)
$tasks | Where-Object { ($_.Status -eq 'Ready') -and ($_.Priority -le 2) }
$tasks | Where-Object { ($_.Name -eq 'Test') -or ($_.Priority -ge 3) }

The first condition keeps only records that are both ready and high priority (priority 2 or lower). The second keeps records named Test or with priority 3 or higher. Choose -and or -or based on whether your filtering task requires all criteria or any one of them.