One of PowerShell’s most valuable functions is its ability to retrieve data. But unfiltered data can be overwhelming and chaotic. The
Where-Object cmdlet in PowerShell is designed to help users filter and manipulate data, turning excessive details into valuable information. Today, we'll delve into the depths of unfiltered data and discover how to transform it into actionable information by utilizing the
Where-Object cmdlet in PowerShell.
The value of filtered data
Network environments are overflowing with data. IP addresses, usernames, services, applications, configurations, attributes, and more are all data points that sysadmins can leverage to make informed decisions, automate processes, and take action.
However, while PowerShell is great at retrieving information, it doesn’t always return it in the most usable format. In fact, PowerShell often returns much more data than is needed.
For example, if I was looking for a specific file, I could run
Get-ChildItem -Recurse against my entire folder directory (please don’t do this), but that would return thousands of results, and I wouldn’t be any closer to locating the file I’m looking for. Instead, I can use the
Where-Object cmdlet to filter against properties, such as the name, size, location, and date, significantly narrowing down the search results.
What does the Where-Object cmdlet do?
Where-Object cmdlet in PowerShell is a filtering mechanism. You can use
Where-Object to filter collections from preceding commands using specific criteria. Objects that meet the conditions of the filter then pass through the pipeline to the next cmdlet.
Where-Object is often preceded by other commands, such as
Get-AppxPackage, but can also be preceded by other arrays and hashtables.
How to structure a Where-Object command
Where-Object cmdlet is pretty straightforward, but some nuances can trip up newcomers.
As mentioned above,
Where-Object is usually preceded by another command and followed by a qualifying filter, like this:
<cmdlet> | Where-Object -Property <property_name> <operator> <filter>
Here’s a real-world example that is probably a bit easier to follow:
In this example, you can really start to see the structure of the command. It begins with the preceding cmdlet
Get-Process. The results of
Get-Process are piped to the
Where-Object is followed by the filter criteria. In this case, we have the
-Property parameter followed by the property
-eq equality operator, and the filter
Something to watch for that can change the look of a
Where-Object command is the use of aliases and positional parameters.
There are two aliases for the
Where. Additionally, the
-Property parameter is positional, which means users don’t even have to include the parameter, just the parameter value. Here are a couple of examples of how the above command could be written and still return the same results.
These examples are the same as the initial command, but they take advantage of aliases and positional parameters to shorten the overall command length. Aliases are great for reducing script length, but they can make it more difficult for beginners to understand what the script is doing.
How to utilize script blocks for more advanced PowerShell filtering
Script blocks are collections of statements contained in braces. They are similar to functions but don’t require a name.
Script blocks can be used in conjunction with the
Where-Object cmdlet. They are especially useful when you need more advanced filtering options. Script blocks allow users to add multiple filters to the same
Here is a basic example of a
Where-Object statement using a script block.
While this example is a bit longer than the first, there are only a few things I need to point out to help you understand what’s going on.
First off, pretend the whole section following the last pipe doesn’t exist. I added that to show the
StartType property in the returned results because it’s not returned by default. It’s not necessary for the command to function.
Next, notice that we replaced the
-Property parameter with the
-FilterScript parameter. This ensures we use the correct parameter set to use a script block. However,
-FilterScript is a positional parameter, and many users leave it off, just as we left off the
-Property parameter in the first set of examples.
You may also wonder about the
$_. symbols. These are automatic variables called
$PSItems. They act as the variable for the current pipeline input item being processed. What’s important is the property following the symbol.
$_.Status uses the
Status property for the filter, and
$_.StartType uses the
Lastly, we combined the two filters with the
How to find files with Where-Object
Let’s look at an example where we utilize
Where-Object to find files matching specific filter criteria. For this example, we’ll search for .jpg and .mov files that are larger than 10 MB and were modified within the last 10 days.
In this example, we utilize the
-Path parameter to narrow down the search directories. We use the
-Include parameter filter for files matching the .jpg and .mov string patterns. In the script block, we add the
$_.Length property and set it to filter for files greater than (
-gt) 10MB. Lastly, we add the
$_.LastWriteTime property and compare it to the current date minus 10 days.
Filter left to increase performance
Filter left is the concept that items should be filtered as early as possible in the command to limit the number of results passed through the pipeline, increasing performance. While it’s not always possible to filter before the
Where-Object cmdlet, many commands provide filterable parameters. A common parameter used to filter at the beginning of the pipeline is the
-Name parameter. Here’s an example:
These two scripts return the same results, but one is more efficient. The first script follows the principle of filter left and immediately filters for services that start with
'Wi*', piping only the results that meet the criteria to the
Where-Object command to then be filtered by the status. The second example returns all the running services and then pipes the full list of services to the
Where-Object command, where the results are then filtered based on the status and name.
Here are results of the two commands.
The difference between these two commands is almost a 65% increase in performance. While this is hardly noticeable on such a small-scale example, the increase in performance can make a significant difference on systems running numerous scripts against large datasets.
Filtered data is useful data
Once you learn the
Where-Object cmdlet, you’ll never stop using it. Hopefully, this guide helps you on your path to PowerShell greatness.
If PowerShell isn’t your cup of tea, but you’d still love to get your hands on tons of useful filtered data, look no further than PDQ Inventory. PDQ Inventory automatically collects loads of information about your endpoints and makes that data easily accessible through a super simple user interface. Try it out for yourself with a 14-day free trial.