More PowerShell Filtering Options



In my previous article on filtering with PowerShell, I gave you an introduction to the tools and techniques you will commonly use when filtering. But filtering can also be done with more than the Where-Object cmdlet. Although once you understand that cmdlet, there are a few other ways you can use it that might simplify your life.

Starting in later versions of PowerShell, you no longer needed to use a filtering scriptblock with $_. For simple filters you can run an expression like this:

get-service w* | where status -eq 'stopped'

Simple PowerShell filtering
Simple PowerShell filtering (Image Credit: Jeff Hicks)

Sponsored Content

What is “Inside Microsoft Teams”?

“Inside Microsoft Teams” is a webcast series, now in Season 4 for IT pros hosted by Microsoft Product Manager, Stephen Rose. Stephen & his guests comprised of customers, partners, and real-world experts share best practices of planning, deploying, adopting, managing, and securing Teams. You can watch any episode at your convenience, find resources, blogs, reviews of accessories certified for Teams, bonus clips, and information regarding upcoming live broadcasts. Our next episode, “Polaris Inc., and Microsoft Teams- Reinventing how we work and play” will be airing on Oct. 28th from 10-11am PST.

If you think about it, I’m actually filtering in multiple ways. First, I’m only getting services that start with ‘w’ and then I am filtering those where the status property is equal to ‘Stopped’.  There was no need to add extra characters and for many people this is easy to read. You can use the concept with any sort of simple comparison.

Get-Process | where workingset -ge 75mb | sort WorkingSet -Descending

Efficient Filtering and Sorting
Efficient Filtering and Sorting (Image Credit: Jeff Hicks)

Here I’m getting all processes where the working set size is greater or equal to 75MB. Note that I perform the sort after the filtering. This is slightly more efficient because I’m not wasting time sorting objects I’m going to discard.

If you’re filtering needs are more complex then you’ll need to turn back to the scriptblock. What you should not do is something like this:

Get-Process | where workingset -ge 50MB | where VM -ge 1000MB

I see examples of this more often than not. This will work but I can tell that the person who wrote it is just getting started and has much to learn about PowerShell. Instead, use a compound filter.
Get-Process | where {$_.workingset -ge 50MB -AND $_.VM -ge 1000MB}

Using a compound filter
Using a compound filter (Image Credit: Jeff Hicks)

This get the same results and it runs a little faster.

By the same token, the reason to filter with Where-Object is because the primary cmdlet you want to use doesn’t provide a way to limit results. Here’s another example I often see that indicates a lack of understanding of PowerShell filtering:

Get-CimInstance win32_volume | Where DriveLetter -eq 'c:' | 
Select SystemName,Caption,Capacity,Freespace,IndexingEnabled,Compressed,FileSystem

Yes, it will work. But Where-Object can’t really filter until all the volumes are returned from Get-CimInstance. On the local machine or when querying a single server, this probably doesn’t matter. But when you start managing at scale and are now querying 100 servers, this type of filtering begins to cost you. I don’t want to get side-tracked into WMI filtering, but Get-CimInstance will accept a WMI filter so learn how to use them.
Get-CimInstance win32_volume -filter "DriveLetter='c:'" -ComputerName $computers | 
Format-Table -groupby @{Name='Drive';Expression={$_.Caption}} -property SystemName,Capacity,Freespace,IndexingEnabled,Compressed,FileSystem

Using a WMI filter
Using a WMI filter (Image Credit: Jeff Hicks)

This is a much better approach, especially when querying many servers. The Get-Ciminstance command will only return objects that match the query, which in this case is any volume object with a driveletter property equal to ‘C:’. That is the only thing that is sent across the network to my desktop. If by chance I was running a filter and on some machines it would return nothing, I’d much rather figure that out “over there” on the server instead of pulling hundreds or thousands of objects across the network, only to discard them because they don’t match my filtering needs.

I will admit that this is not an absolute rule. Based on your filtering needs, you may have no choice but to bring objects through the pipeline and filter with Where-Object. Some of the filtering with the Active Directory cmdlets can be a bit tricky. But even if you have a complex set of filtering criteria, try to use the initial cmdlet to provide as much filtering as it can. That way you are processing as small a set of objects as possible with Where-Object.

If you want to read one more useful filtering technique, read Filtering PowerShell with the Where Method on Petri IT Knowledgebase.

Related Topics:


Don't have a login but want to join the conversation? Sign up for a Petri Account

Comments (0)

Leave a Reply

External Sharing and Guest User Access in Microsoft 365 and Teams

This eBook will dive into policy considerations you need to make when creating and managing guest user access to your Teams network, as well as the different layers of guest access and the common challenges that accompany a more complicated Microsoft 365 infrastructure.

You will learn:

  • Who should be allowed to be invited as a guest?
  • What type of guests should be able to access files in SharePoint and OneDrive?
  • How should guests be offboarded?
  • How should you determine who has access to sensitive information in your environment?

Sponsored by: