As I mentioned yesterday, PowerShell is built around objects. And so it doesn’t just work with plain text, when selecting data or doing things with it. Objects are everything in PowerShell. And one of PowerShell’s greatest strengths is how you can filter those objects in the pipeline. Enter Where-Object, a cmdlet that allows you to filter objects based on specific conditions.

Whether you’re filtering files, processes, or Active Directory users, Where-Object is your go-to tool for narrowing down results. Let’s walk through how to use Where-Object effectively, in the CLI and in your scripts.

Basic Syntax

The basic syntax for Where-Object is:

1
<Command> | Where-Object { Condition }

<Command> is any PowerShell command that outputs objects.
{ Condition } is a script block where you define your filtering criteria.

For example, let’s list all processes consuming more than 100 MB of memory:

1
Get-Process | Where-Object { $_.WorkingSet -gt 100MB }

Here:
$_ represents the current object in the pipeline.
WorkingSet is a property of the process object that shows memory usage.
-gt means “greater than.”

Understanding $_ and Object Properties

The $_ symbol is a special variable that refers to the current object being processed in the pipeline. You can access any property of the object using dot notation.

For example:
$ refers to the whole object.
$
.<PropertyName> accesses a specific property of the object.

Here’s an example with files:

1
Get-ChildItem -Path "C:\SomeFolder" | Where-Object { $_.Length -gt 1MB }

This command retrieves all files in C:\SomeFolder larger than 1 MB.

Filtering with Comparison Operators

Where-Object relies heavily on comparison operators to filter objects. Here are the most common operators:

OperatorMeaningExample
-eqEqual to$_Name -eq “example.txt”
-neNot equal to$_Name -ne “example.txt”
-gtGreater than$_Length -gt 1MB
-ltLess than$_Length -lt 500KB
-geGreater than or equal to$_Length -ge 2MB
-leLess than or equal to$_Length -le 100KB
-likeWildcard match$_Name -like “*.log”
-notlikeNot a wildcard match$_Name -notlike “*.log”
-matchRegular expression match$_Name -match “log\d+”

Example: List files ending with .log:

1
Get-ChildItem -Path "C:\Logs" | Where-Object { $_.Name -like "*.log" }

Simplified Syntax in PowerShell 3.0+

Starting with PowerShell 3.0, you can use a simplified syntax for Where-Object. Instead of writing { $_.Property -eq Value }, you can write:

1
<Command> | Where-Object Property -eq Value

For example:

Traditional Syntax:

1
Get-Process | Where-Object { $_.CPU -gt 100 }

Simplified Syntax:

1
Get-Process | Where-Object { $_.CPU -gt 100 }

Both commands achieve the same result.

Multiple Conditions with -and and -or

You can combine multiple conditions using -and (logical AND) and -or (logical OR).

For example:
Processes using more than 100 MB memory AND more than 10 seconds of CPU time:

1
Get-Process | Where-Object { $_.WorkingSet -gt 100MB -and $_.CPU -gt 10 }

Files larger than 1 MB OR files with the .log extension:

1
Get-ChildItem -Path "C:\Logs" | Where-Object { $_.Length -gt 1MB -or $_.Name -like "*.log" }

Filtering Null or Empty Properties

Sometimes you need to filter objects with null or empty properties. For example, to find processes with a null value in the Path property:

1
Get-Process | Where-Object { $_.Path -eq $null }

Real-World Example: Filtering Services

Let’s list all services that are currently stopped:

1
Get-Service | Where-Object { $_.Status -eq 'Stopped' }

Output:

1
2
3
4
Status   Name               DisplayName
------   ----               -----------
Stopped  wuauserv           Windows Update
Stopped  sppsvc             Software Protection

Want to find only services that start with “Win”? Use the -like operator:

1
Get-Service | Where-Object { $_.Name -like "Win*" }

Best Practices for Using Where-Object

  1. Filter Early: Use Where-Object as early as possible in the pipeline to reduce the amount of data passed downstream.
  2. Simplify Syntax: Use the simplified Property -eq Value syntax for clarity.
  3. Be Efficient with Large Datasets: For large data sets, consider using cmdlet-specific filtering options (e.g., -Filter or -Include) before relying on Where-Object.

###Takeaway…

The Where-Object cmdlet is a cornerstone of PowerShell scripting that allows you to filter objects in the pipeline based on conditions. Whether you’re querying processes, files, services, or custom objects, Where-Object gives you the flexibility to filter data precisely.

Start practicing with Where-Object in your scripts today. You’ll quickly see how much cleaner and more efficient your PowerShell output becomes! 🚀