PowerShell is a command line and scripting language for system administration and automation in Windows, and is a vital part of every Windows administrator or developer’s toolkit. Filtering the output of PowerShell commands using Where-Object allows you to quickly find relevant data for display, or perform operations on a subset of objects based on your filter criteria.
This guide explains how to use Where-Object to filter objects and data in PowerShell, and includes practical examples that you can copy and paste for use in your own code. It also explains performance considerations and best practices for using Where-Object in your PowerShell scripts.
Understanding the Where-Object PowerShell cmdlet
The Where-Object PowerShell CmdLet (a CmdLet is a PowerShell command used for automation) filters a collection of objects from a command to only those that match your search criteria.
The most commonly used syntax and parameters for Where-Object is as follows:
[ Command ] | Where-Object [ -Property ] [ -Value ] [ Operator ]
Note that:
- [ Command ] is the command that has its output filtered by Where-Object.
- [ -Property ] is the property of the object to compare, supplied as a string.
- [ -Value ] is the value to compare the property against, supplied as an object or string.
- The final parameter is the comparison [ Operator ] to use: -eq (equal to), -ne (not equal to ), -gt (greater than), -lt (less than), -ge (greater than or equal to), -le (less than or equal to).
Output is piped to Where-Object. You can see other syntax options in the PowerShell documentation. It is also possible to supply your own more complex filtering criteria as a code block, as shown in the examples later in this article.
Practical examples of using Where-Object to filter objects
The best way to see how to use Where-Object is to see it in action. Below are several simple examples showing basic usage using built-in comparison operators and advanced usage that implements custom criteria in script blocks. These examples include how to filter by multiple values, using regex, and filtering by date.
Following that are several complete PowerShell commands that use Where-Object to perform common scripting tasks like cleaning up log files, finding processes with high memory usage, filtering Active Directory users, and searching event logs.
Filtering single values
This example shows how to filter to a single value using the -eq comparison operator:
# Filter running processes to those with the name ‘powershell’
Get-Process | Where-Object Name -eq ‘powershell’
Filtering by multiple values
This example shows how to filter by multiple values. It filters the list of running processes from Get-Process to those named “winlogon” and “explorer” (both of which should be running for every logged-in user):
# Filter running processes named ‘winlogon’ or ‘explorer’
$names = @(‘winlogon’, ‘explorer’) # Define an array containing the multiple search values
Get-Process | Where-Object { $names -contains $_.Name }
The curly braces in this example denote a PowerShell script block that contains a collection of expressions. Note also the use of $_ — a shortcut that represents the object being compared. In this case, it’s used to supply the Name property of the object to the comparison.
Using regular expressions
Where-Object can also be used with arrays. Regex can be used to filter any kind of object, providing a way to add complex conditions for filtering by the contents of strings:
# Filter an array of emails to those from a specific domain
$emailAddresses = @(“[email protected]”, “[email protected]”, “[email protected]”) # Define an array of email addresses
$emailAddresses | Where-Object { $_ -match ‘@test.com$’ }
Note that you could also use the array Where() method, discussed later in this article.
Filtering by date
For commands that return objects with date properties, you can filter using DateTime objects returned by Get-Date:
# Find files in the current directory that were modified in the last 14 days
Get-ChildItem -Path . | Where-Object { $_.LastWriteTime -GT (Get-Date).AddDays(-14) }
You can also filter between dates by supplying a date range:
# Find Windows event log entries from the last week
$startDate = (Get-Date).AddDays(-7) # Note the use of a negative number to set the date to the past
$endDate = Get-Date
Get-EventLog -LogName Application | Where-Object { $_.TimeGenerated -ge $startDate -and $_.TimeGenerated -le $endDate }
Advanced examples demonstrating custom criteria in script blocks
As shown in the above examples, script blocks can be used to contain multiple comparison expressions. You can perform more complex filtering using Where-Object by supplying multiple criteria and conditions in script blocks. Here are a few examples:
# Filter processes with CPU usage greater than 75%
Get-Process | Where-Object { $_.CPU -gt 75 }
# Find running services that have a name starting with ‘Win’
Get-Service | Where-Object { $_.Status -eq ‘Running’ -and $_.Name -like ‘Win*’ }
# Find files in the current directory that are larger than 3MB and have been modified in the last 30 days
Get-ChildItem -Path . | Where-Object { $_.Length -gt 3MB -and $_.LastWriteTime -gt (Get-Date).AddDays(-30) }
Common real-world Where-Object examples
In addition to the examples above, here are some further PowerShell commands that are commonly required for automation and system administration:
# Find .txt files in the current directory
Get-ChildItem -Path . | Where-Object Extension -eq ‘.txt’
# Delete log files at a given path older than 90 days
Get-ChildItem -Path ‘C:PathToLogs’ -Filter ‘*.log’ | Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-90) } | Remove-Item
# List processes that use more than 1000 MB of memory
Get-Process | Where-Object { $_.WorkingSet -gt 1000MB } | Select-Object Name, WorkingSet
# Search for Active Directory users who are members of a specific group (marketing) and have a specific job title (Director)
Import-Module ActiveDirectory
Get-ADUser -Filter { MemberOf -eq ‘CN=Marketing,OU=Groups,DC=example,DC=com’ -and Title -eq ‘Director’ }
# Find Windows event log entries that are errors related to a specific application (MyApplication)
Get-EventLog -LogName Application -EntryType Error | Where-Object { $_.Source -eq ‘MyApplication’ }
Note the combined use of Where-Object and Select-Object in this example to extract relevant data from results.
Difference between Where-Object and other filtering methods
There are several ways to filter data in Powershell, some dealing with objects, and some dealing with text. They do not behave the same way, so you should pick the one that best suites each scenario:
- Where-Object: Filter collections of objects piped to the command so that only matching objects remain.
- Select-Object: Additionally able to filter object properties, for example returning a collection of objects, but only including the ‘name’ property of each.
- Array Where() method: Filter arrays based on supplied conditions.
- Filter parameter: Some cmdlets will include a -Filter parameter for searching their output.
Performance considerations when filtering data
Data filtering can be a resource-intensive task. PowerShell commands, especially when interacting with databases or Active Directory, can potentially output multiple thousands of records, and using Where-Object to process and filter each one is not the most efficient way to search large sets of data.
Many PowerShell commands will include a -Filter parameter that is optimized for searching using that command. If a -Filter parameter is available, it’s recommended to use it to reduce the data as much as possible before passing it to Where-Object.
For example, if you are working with Active Directory data using the Get-ADUser, and want to retrieve a list of users from a certain department, and then perform different actions based on their job role, you should use -Filter to limit the results to the department, and you can then use Where-Object to perform actions based on Job role to the smaller list of objects.
If your Powershell script is taking too long to execute and you suspect that a command containing Where-Object is to blame, you can assess its performance using the Measure-Command cmdlet to measure the time it takes for the command to complete.
Best practices and common pitfalls when using Where-Object in PowerShell
There are a few common pitfalls that users encounter when using Where-Object that can be solved with the following best practices:
- “Filter left”: Use cmdlet specific -Filter or other search parameters as early in your PowerShell commands as possible (that is, as far to the left of the command as possible) to maximize efficiency.
- Use Select-Object to filter out unneeded properties: This improves performance when dealing with large amounts of data (that you can’t otherwise filter using cmdlet-specific functions).
- Keep it simple: Avoid complex conditions in script blocks and break things down wherever possible to improve performance and make debugging easier.
- Use comparison operators correctly: Make sure you understand what your filter parameters and script blocks are doing to avoid unexpected results.
- Keep your scripts readable: You can use ? as an alias for Where-Object to shorten commands to make them easier to read. You should also use white space and indentation to keep your code well-formatted and easy to read, as well as add comments noting what each line in your PowerShell script is meant to do (in case you come back in months or years to tweak something and forget what the purpose of a command was).
To assist with debugging Where-Object commands, you can use the common PowerShell verbose parameter to print detailed information about the operation in progress. For example:
$VerbosePreference = “Continue”
Get-Process | Where-Object { $_.CPU -gt 75 } -Verbose
You should also use try-catch blocks to handle unexpected errors gracefully.
Data filtering using PowerShell Where-Object lets you display relevant information from cmdlets, search for files and processes, and sort through results from any PowerShell command that returns results as objects, including tools for working with Active Directory. To see how Where-Object can assist with repetitive system administration tasks, check out our tutorial on how to use PowerShell for automation.