
close
close
Over the course of a few articles, I have demonstrated a variety of filtering techniques and strategies. I want to wrap up our exploration with a filtering method you may not know about as it is not well documented. And it is just that, a method. There Where() method was introduced in PowerShell 4.0 for Desired State Configuration (DSC) but you can use it in your everyday PowerShell work. Everything you know about Where-Object still applies.
You normally would think about running a command like this:
get-service | where status -eq 'stopped'
But the Where() method belongs to any object collection.
advertisment
(get-service).where({$_.status -eq 'stopped'})
This produces the same result in a fraction of the time. The syntax looks like:
<a collection objects>.where({<filtering script with $_})
If you think you might need to so do several filtering operations, you can save the initial results to a variable first.
$p = Get-Process
Then you can can filter like this:
$p.where({$_.ws -ge 80mb})
Although most of the time (at least the way that I work) we know in advance that filtering will take place. By wrapping the command in parentheses, we’re telling PowerShell to hold the results as kind of an in-memory variable. This Where method really shows its worth with large collections.
advertisment
(dir c:\scripts -file -Recurse).Where({$_.length -ge 5MB})
I could run this with the traditional Where-Object and get the same result but this is slightly faster.
But there’s more than mere performance here. Take a look at this:
$a,$b = (Get-Service).Where({$_.status -eq 'stopped'},"Split")
Not only am I filtering but I’m also telling the Where() method to split the results. This selection mode will filter accordingly and write the commands that match the filter to the pipeline first. It will then pipe everything that didn’t match to the pipeline. My PowerShell syntax will thus have all stopped services in $a and everything else in $b.
You can also get the first or last matching filtered object.
(Get-Service).where({$_.status -eq 'stopped'},"First",1)
advertisment
Get-Service | where {$_.status -eq 'stopped'} | Select -first 1
But not nearly as much fun!
(1..10).where({$_ -eq 5},"until")
(1..10).where({$_ -eq 5},"skip")
(1..10).where({$_ -eq 5},"skipuntil")
<a collection objects>.where({<filtering script with $_},[split|skip|skipuntil|until].[number of items to return])
The default is to return all objects but you have fine control.
(1..10).Where({$_ -gt 5},"skip",1)
If you try this out, and I hope you will, PowerShell writes 6 to the pipeline. Or in other words, I told PowerShell to “find all the numbers greater than 5 and display the first one that matches the criteria.” As I mentioned, I haven’t found many practical examples for these Where() method parameters, but maybe you have something in mind. If so, I’d love to hear about it.
The Where() method is a smart addition to your PowerShell scripts when working with a large collection of objects. I think you’ll see a noticeable improvement in performance. Remember this requires PowerShell 4 and later so you should add a #Requires -version 4.0 comment to your script file.
In the mean time, give all of this a spin and let me know what you think.
More in PowerShell
Microsoft’s New PowerShell Crescendo Tool Facilitates Native Command-Line Wraps
Mar 21, 2022 | Rabia Noureen
Most popular on petri