The Where-Object cmdlet and the Where method both allow you to filter arrays in PowerShell. In this post, you will learn the difference between the two filters.

PowerShell, like all other scripting languages, has ways to bring different pieces of data together into a collection. These "collections" refer to different types of variables that hold more than one value. For example, two popular types of collections in PowerShell are arrays and hashtables. The scenario and type of collection you're filtering will determine the best way to filter necessary information from each of these collections.

Provider-specific filters ^

To explain collection filtering, let's first go over a few of the common ways that PowerShell filters things. First, we have provider-specific filters. These filters apply at the PowerShell provider level. These filters are not PowerShell-specific per se; PowerShell just passes the filter to the appropriate provider. You'll typically know a provider-specific filter when you see a command using the Filter parameter. This Filter parameter typically accepts a string or a scriptblock; it then passes this to the provider.

A typical example is the Get-ChildItem cmdlet. You'll notice that the Filter parameter is simplistic in that you can only perform filtering on the file name itself. A common filter is *.txt, ensuring all files that Get-ChildItem returns are text files, for example. Another example is the Filter parameter on the Active Computer PowerShell cmdlets. This time, however, instead of using the FileSystem provider, it uses the ActiveDirectory provider. For a list of PowerShell providers, type help about_providers in any PowerShell console.

It's always a good idea to use provider-specific filters as much as possible. Since the filtering is closer to the source and this method doesn’t have to send the objects over the PowerShell pipeline, performance is much faster.

Where-Object ^

The Where-Object command is a sort of generic filtering command. Use this command to filter any kind of object in PowerShell. The Where-Object command has a FilterScript parameter, which is a scriptblock that allows the user to place code in it. If this scriptblock contains code that returns anything but $false, $null, or an empty string, it will allow whichever object the user passes to it.

For example, let's say I've got a folder full of files. I'd like to see only text files and only those text files modified today. To make this happen, I can use the provider-specific filter with the Get-ChildItem command and also the Where-Object command.

Get-ChildItem -Path C:\Folder -Filter *.txt -Recurse | Where-Object -FilterScript { ([datetime]$_.LastWriteTime).Date -eq '7/16/2016' }

Above, you can see that I'm enumerating all text files in the C:\Folder folder and then using Where-Object to filter on the LastWriteTime property and only find files written on 7/16/2016. Where-Object works because the scriptblock { ([datetime]$_.LastWriteTime).Date -eq '7/16/2016' } returns $true. I can put any code in this scriptblock and as long as it returns something, it will return whatever the InputObject parameter is (in this case, Get-ChildItem is passing it via a pipeline).

I can do the same for other object types as well, such as arrays.

@(1,2,3,4,5,6) | Where-Object -FilterScript { $_ -gt 1 }
Filtering arrays with Where Object

Filtering arrays with Where Object

The Where() method ^

Another method of collection filtering introduced in PowerShell v4 is the where() method. This method only works on arrays. This means that to use this method, you must first convert whatever you're working with to an array.

To use this method, let's use our example above. This time instead of piping objects to the Where-Object command, I'm going to create an array and then do my filtering. This essentially performs the same task but in a different way.

$files = Get-ChildItem -Path C:\Folder -Filter *.txt -Recurse
$files.where({ ([datetime]$_.LastWriteTime).Date -eq '7/16/2016' })

Notice this time I can't use the pipeline because where is an actual method on the $files array. I must invoke it using a dot. Also, notice that to perform the filtering, Get-ChildItem must find every file and only after retrieving all of the files can it filter them for the LastWriteTime property.

Subscribe to 4sysops newsletter!

This method might be slower, depending on how many files Get-ChildItem returns due to this setback. However, this is usually always faster than using the pipeline to send objects to Where-Object.

  1. Luc Fullenwarth 5 years ago

    Probably in the second paragraph of the “Provider-specific filters” subtitle,
    you wanted to write “Active Directory PowerShell cmdlets”
    instead of “Active Computer PowerShell cmdlets”…

    By the way, I was always using the -FilterScript parameter.
    But I recently discovered that if you need only one filter,
    there is a shorter way to filter out.

    For example, formerly I used:
    Get-Service | Where-Object -FilterScript {$_.Status -eq ‘Stopped’}
    Now I use:
    Get-Service | Where-Object -Property Status -eq ‘Stopped’

    Thanks again Adam for your good posts!

  2. Summa Lai 4 years ago

    actually ? where, where-object all the same

    Get-Alias ?

    Get-Alias where

    and then you can see both are the alias of where-object


    • Ray 4 years ago

      Hmm, you completely missed the point. Where is the alias of  Where-Object, but Adam is showing the difference between Where-Object and Where() method. The Where() method is different and not an alias of Where-Object.


Leave a reply

Your email address will not be published.


© 4sysops 2006 - 2022


Please ask IT administration questions in the forums. Any other messages are welcome.


Log in with your credentials


Forgot your details?

Create Account