PowerShell Where-Object: Filter Objects With Examples

PowerShell Where-Object filters objects in the pipeline. You give it a condition in a script block, and it passes on only the objects where the condition is true. Here it keeps orders over $900:

$orders = @(
    [pscustomobject]@{ Id = 1001; Customer = 'Alice Johnson'; State = 'TX'; Status = 'Shipped';   Total = 1250 }
    [pscustomobject]@{ Id = 1002; Customer = 'Bob Smith';     State = 'CO'; Status = 'Pending';   Total = 980 }
    [pscustomobject]@{ Id = 1003; Customer = 'Carol Davis';   State = 'WA'; Status = 'Shipped';   Total = 15000 }
    [pscustomobject]@{ Id = 1004; Customer = 'Dan Miller';    State = 'FL'; Status = 'Cancelled'; Total = 425 }
    [pscustomobject]@{ Id = 1005; Customer = 'Alice Johnson'; State = 'TX'; Status = 'Pending';   Total = 310 }
)

$orders | Where-Object { $_.Total -gt 900 } | Select-Object -Property Id, Customer, Total

Output:

  Id Customer      Total
  -- --------      -----
1001 Alice Johnson  1250
1002 Bob Smith       980
1003 Carol Davis   15000
PowerShell Where-Object filters objects by a property value
Only orders with a total over 900 (PowerShell 7)

$_ is the object being checked. The other examples in this guide use the same five sample orders in $orders, so run the $orders = @(...) part of the script above once in your session.

I ran each example in PowerShell 7.6 and Windows PowerShell 5.1. Apart from the timings, the only difference was one count, which I show below.

Script block vs simplified syntax

For a single condition, you can skip the braces and $_. This is the simplified syntax:

$orders | Where-Object Status -EQ 'Pending' | Select-Object -Property Id, Customer, Status

Output:

  Id Customer      Status
  -- --------      ------
1002 Bob Smith     Pending
1005 Alice Johnson Pending

It’s shorter, but it only takes one condition. For -and, -or or any calculation, use the script block. The Where-Object documentation lists every operator parameter.

For more than one condition, you’ll need the script block form, as shown in Where-Object with multiple conditions.

Common Where-Object operators

OperatorKeeps objects whereExample
-eq / -neThe value is equal / not equal$_.Status -ne 'Cancelled'
-gt / -ltThe value is greater / less than$_.Total -gt 900
-like / -notlikeThe value matches a wildcard$_.Customer -like 'A*'
-matchThe value matches a regex$_.Customer -match 'son$'
-in / -notinThe value is in a list$_.State -in 'TX', 'FL'

Where-Object not equal

To exclude values, use the “not” version of each operator:

"Not cancelled:   $(($orders | Where-Object { $_.Status -ne 'Cancelled' }).Id -join ', ')"
"Not like 'A*':   $(($orders | Where-Object { $_.Customer -notlike 'A*' }).Id -join ', ')"
"Not in TX or FL: $(($orders | Where-Object { $_.State -notin 'TX', 'FL' }).Id -join ', ')"

Output:

Not cancelled:   1001, 1002, 1003, 1005
Not like 'A*':   1002, 1003, 1004
Not in TX or FL: 1002, 1003

Case-sensitive matching

Text comparisons ignore case by default. Add a c to the operator, like -ceq, when case matters:

"-eq 'shipped':  $(@($orders | Where-Object { $_.Status -eq 'shipped' }).Count) orders"
"-ceq 'shipped': $(@($orders | Where-Object { $_.Status -ceq 'shipped' }).Count) orders"

Output:

-eq 'shipped':  2 orders
-ceq 'shipped': 0 orders

Filter on multiple conditions

Combine conditions with -and and -or inside one script block:

$orders | Where-Object { $_.State -eq 'TX' -and $_.Status -ne 'Cancelled' } | Select-Object -Property Id, Customer, Status

Output:

  Id Customer      Status
  -- --------      ------
1001 Alice Johnson Shipped
1005 Alice Johnson Pending