You do a lot of Filtering output in PowerShell, primarily using the Where-Object cmdlet. This blog post will show you a few ways to do that. And that you shouldn’t use the “old” method when filtering only one property 😉

What does Where-Object do?
“The Where-Object cmdlet selects objects that have particular property values from the collection of objects that are passed to it. For example, you can use the Where-Object cmdlet to select files that were created after a certain date, events with a particular ID, or computers that use a particular version of Windows.”
The #1 reason you shouldn’t use it for
I wrote it in a blog post a while back here, but you should always try to filter as much data as possible before letting Where-Object filter the returned data. It’s just faster!
The old and new methods with one filter
I often see Where-Object used in the old “method” when filtering just one property. This is a method that was valid until PowerShell v3.0.
The syntax was:
C:\Users\HarmVeenstra> Get-ChildItem | Where-Object {$_.Name -match "Update"}
Directory: C:\Users\HarmVeenstra
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 5-11-2023 19:37 101 update.ps1
The new syntax from PowerShell v3.0 and higher is:
C:\Users\HarmVeenstra> Get-ChildItem | Where-Object Name -match "Update"
Directory: C:\Users\HarmVeenstra
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 5-11-2023 19:37 101 update.ps1
It saves a few characters and seems less complicated for the starting PowerShell user 😉
Using Where-Object with multiple filters
In the example above, only one property was filtered for something specific (In the example, I searched for any file in the current directory that has an update in its filename). But what if you want to filter on multiple properties?
Filtering for all files with “update” in its name and with the “.ps1” file extension:
C:\Users\HarmVeenstra> Get-ChildItem | Where-Object {$_.Name -match "Update" -and $_.Name -match "ps1"}
Directory: C:\Users\HarmVeenstra
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 5-11-2023 19:37 101 update.ps1
Filtering for all files with “update” in their name or with the “.ps1” file extension will also show files with update in their name.
C:\Users\HarmVeenstra> Get-ChildItem | Where-Object {$_.Name -match "Update" -or $_.Name -match "ps1"}
Directory: C:\Users\HarmVeenstra
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 12-1-2024 16:56 0 test.ps1
-a--- 12-1-2024 16:53 0 testupdate.txt
-a--- 5-11-2023 19:37 101 update.ps1
Using Where-Object with multiple conditions
You can also use multiple conditions when filtering in a ScriptBlock format. In the example below, I search for files matching the name “Untitled” and have the “png” extension, but with an extra filter only showing files older than 120 days using the LastWriteTime property.
C:\Temp> Get-ChildItem | Where-Object {($_.Name -match "Untitled" -and $_.Name -match "png") -and $_.LastWriteTime -lt (Get-Date).AddDays(-120)}
Directory: C:\Temp
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 23-9-2021 23:06 16008812 Untitled.4png.png
-a--- 5-10-2021 23:33 45190 Untitled1.png
-a--- 16-6-2022 21:28 1582520 Untitled23123.png
-a--- 9-6-2022 20:23 19832 Untitled4.png
It retrieved four files in total. Without the extra filter on the LastWriteTime property, it would show these six files in total:
C:\Temp> Get-ChildItem | Where-Object {$_.Name -match "Untitled" -and $_.Name -match "png"}
Directory: C:\Temp
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 23-9-2021 23:06 16008812 Untitled.4png.png
-a--- 10-12-2023 21:25 9936 Untitled.png
-a--- 5-10-2021 23:33 45190 Untitled1.png
-a--- 5-10-2023 11:13 360114 Untitled2.png
-a--- 16-6-2022 21:28 1582520 Untitled23123.png
-a--- 9-6-2022 20:23 19832 Untitled4.png
Wrapping up
In the examples above, I showed you how the filter properties retrieve only the things you want using Where-Object. If needed, you can filter for one or more properties with multiple conditions. You can find more information about the parameters with some extra examples.
I always get confused when doing multiple operators and when to wrap it within the script block.
C:\Users\HarmVeenstra> Get-ChildItem | Where-Object {$.Name -match “Update” -or $.Name -match “ps1”}
Directory: C:\Users\HarmVeenstra
Mode LastWriteTime Length Name
—- ————- —— —-
-a— 12-1-2024 16:56 0 test.ps1
-a— 12-1-2024 16:53 0 testupdate.txt
-a— 5-11-2023 19:37 101 update.ps1
Is that example looks like you did 3 operators, but didn’t wrap it.
If multiple statements, then use {}’s. If single statement, don’t 😉