Skip navigation

How To Filter Objects in PowerShell

Watch this video to learn techniques for working with PowerShell output, focusing on objects in the pipeline.

In this video tutorial, Brien Posey demonstrates various techniques for working with PowerShell output, particularly when dealing with objects in the pipeline. Transcript below.

 

Posey starts by explaining the concept of objects in PowerShell and shows examples using the Get-Service and Get-Process cmdlets.

He then covers the following techniques:

The following transcript has been lightly edited for clarity and brevity.

Transcript:

Brien Posey: Hello, greetings, and welcome. I'm Brien Posey. In this video, I want to show you a few easy techniques for working with PowerShell output, particularly when you're dealing with objects in the pipeline.

So, let's go ahead and get started.

Objects in PowerShell (With Examples)

The first thing that I'm going to do is type a common PowerShell cmdlet called Get-Service.

When I press Enter, you can see that a number of pieces of information are returned by this command.

You can see that we have a number of different records. Each one of these is a system service that is installed on this particular machine. So, for each one, you can see the service name and the name column, the status of that service, and the services display name.

This is an example of an object. We can act on this object and retrieve individual pieces of information rather than having to look at the list as a whole.

Now, this isn't unique to the Get-Service cmdlet. This is a very common principle within PowerShell.

Let me show you another example. In this case, I'm going to type Get-Process. I'll press Enter, and what I get is a list of all the various processes that are running on this machine. So, if I scroll up a little bit, you can see the handles for each process. We have some other pieces of information, such as the working set. That's the memory that the process is using, the CPU resources, the processor ID, the process name, and several other things.

The point is that very often PowerShell output is an object format and you can look at those objects and extract very detailed information from them.

Filtering Output Using the Get-Process Cmdlet

I want to begin by showing you an extremely simple filtering technique.

Let's suppose that rather than looking at every single process running on this machine, we wanted to look at the Explorer process. Now obviously, you can see the Explorer process right here, but let's suppose that we didn't want to filter through the list and just wanted to look at this one specific process.

Well, what we could do in that case is simply type the name of the process that we want to examine. Let me show you how this works.

I'll type the following:

Get-Process Explorer

And when I do, I see that one specific process.

Using the Out-Gridview Cmdlet To Display Output in an Interactive Table Format

Now, there are a number of other ways that we could filter this list and drill down and retrieve very specific pieces of information. Before I show you the various command line options, though, there's one other trick that I want to show you. And that's to use a command called Out-Gridview. Let me show you how this works.

As you'll recall, when I type Get-Process and just press Enter without listing a specific process, I get a long list of all the processes that are running on this machine. Now, if I wanted to put this in a more usable format, then I can append the pipe symbol and the Out-Gridview cmdlet.

Get-Process | Out-Gridview

In PowerShell, the pipe symbol tells PowerShell that we want to take the output of one command and use it as input for the next command. So, we're taking the output of the Get-Process command – in other words, everything that you see above the command line – and then we're using that as input for the Out-Gridview command. The Out-Gridview command puts all of this information into an interactive table.

Let me show you what this looks like. So, here we have a list of all the processes that are running on this machine, and it's in an interactive format. We can sort the various columns by clicking on them. We can also filter. You'll notice the Add Criteria button right here. So, I could click on this button, and you'll notice checkboxes relating to the columns that are being displayed. We can select a specific checkbox. I'll select CPUs. I'll click Add. And so, then you can see add CPUs contains. And if I click on contains, I have different choices: contains, does not contain, start with, equals, does not equal, ends with, is empty, is not empty. I'm just going to click on “equals,” and I'm just going to type 0.00 since we clearly have some processes that are using 0% CPU. Immediately, we get a filtered list showing only those processes that have 0.00% CPU usage.

So, that's just a really quick example of how the Out-Gridview command works.

Using the Select-Object Cmdlet To Retrieve Specific Properties From Objects

Now, as I mentioned, there are a variety of techniques that we can use at the command line to perform similar types of filtering. So, let's take a look at a few of those options.

The first thing that I want to show you is that PowerShell has a lot more information available to it than what is shown by default. I showed you the Get-Process cmdlet already, and I showed you how you could type the name of an individual process if you only wanted to look at that one specific process. For example, I'll type Explorer and press Enter, and here we see some basic information related to the Explorer process.

Now, the interesting thing is there's way more information available than what's shown on the screen right here. And this isn't unique to the Get-Process cmdlet. Most of the PowerShell cmdlets that output information as an object will hide some of that information by default, and you can drill down into PowerShell and get access to that hidden information.

So, let's take a look at how this works. I'm going to type:

Get-Process Explorer | Select-Object *

I’ll go ahead and press Enter. And when I do, you'll see a great long list of information pertaining to the Explorer process. Everything that you see is related to this one process, not to all of the processes. Just the Explorer process. And as I scroll up, you can see how much information is truly being displayed. So, we have a ton of information that's made available to us.

Let's look at how to drill down into this information and see the information that we're interested in. So, what I'm going to do is I'm going to repeat the command that I just typed, only this time instead of using an asterisk I'm going to type some specific column names.

Get-Process Explorer | Select-Object ProcessName, WorkingSet, TotalProcessorTime, Threads

I'll press Enter. And what we see as a filtered output. It shows us exactly the columns that I specified: ProcessName, WorkingSet, TotalProcessorTime, and Threads.

Now incidentally, if you happen to do something like this and you end up with an empty column, it's possible no information exists for that column. But it's also possible that you made a spelling error. So, for example, if I were to repeat this command and I were to misspell Threads (I'll just drop the “s” on the end), you'll notice that the Threads column, which is misspelled as “Thread,” is now empty. So that's why in many cases you may see that you're not getting visible output.

But let me go ahead and put this back the way that it was. There's something that I want to show you. So, we can see the ProcessName, the WorkingSet memory (there are ways of putting that into a more usable format, but that's kind of beyond the scope of this video), and the TotalProcessorTime. But you'll notice that the Threads column looks a little bit different: We have all of these numbers, and those numbers are in braces. And then we have these three dots.

{11352, 14548, 17384, 17364}

Anytime that you see output from an object like this (shown in braces with a series of dots), it means that PowerShell is hiding more information. So, I already showed you how to use Select-Object to get that information. But we're using Select-Object right now. You can see we're using Select-Object and then we're specifying Threads as one of the objects.

So, if I were to simply type:

Get-Process Explorer | Select-Object Threads

That wouldn't give me any more information than what we've already got.

So, the way that you would drill down into the Threads – or into any piece of information that is enclosed in braces and has the three dots – is you have to expand the property.

Let me show how this works. I'm going to repeat the command that I just typed, but I'm going to do things just a little bit differently. I'm going to add -ExpandProperty:

Get-Process Explorer | Select-Object -ExpandProperty Threads

When I press Enter, we have all this information that's generated. And remember, we're only looking at Threads right now, and you can see how much information is truly there. All of this was hidden.

Okay, so that's a huge list of information. What if we wanted to narrow this down a little bit, and look at a specific piece of information related to the Threads? Well, what we could do in a situation like that is use a second Select-Object command. Remember, we've already expanded the Threads property. So now because it's expanded, we can use a normal Select-Object command to look at individual attributes of the threads.

Let me show you what I'm talking about. What I'm going to do is repeat the same command that I just typed, then I'm going to append a pipe symbol, and then I'm going to type Select-Object. And let's take a look at the object ID.

Get-Process Explorer | Select-Object -ExpandProperty Threads |Select-Object ID

I'll press Enter. And so, what I get is the object ID for every thread associated with the Explorer process. That's what I'm looking at right now.

Using the Where-Object Cmdlet To Filter Output Based on Various Conditions

So, let's move on and talk about some other ways that we can filter the output.

What I'm going to do is I'm going to use the Get-Process cmdlet again. And I already showed you how you could type the name of one specific process and get information related only to that process. For example, to get information related to the Explorer process, we would simply type Get-Process Explorer, and now we have information related to the Explorer process.

But we can also use a command called Where-Object to retrieve specific information.

Let's look at how this works. I'm going to type:

Get-Process | Where-Object{$_.name -eq ‘Explore’}

What the $_. does is examine the current object. So, in this case, we're examining the Process object, and we're looking at the names of all the various processes.

Dash eq (-eq) is equals. So, we're checking for a situation where the ProcessName is equal to ‘Explorer’.

I'll press Enter. And we get the same result as before.

Now, obviously, this was kind of a long way of getting the same result that we could have gotten just by typing Get-Process Explorer. But we can search for other things, as well. We're not limited to just looking for the name.

So, we can use that same technique to filter other pieces of information. Here's an example of how that might work.

Get-Process | Where-Object{$_.HandleCount -eq 2465}

We're checking the HandleCount for all the process objects. And we're looking for a HandleCount that's equal to 2465.

You'll notice that I don't have quotes around 2465 because we're looking for a number rather than a string.

I'll press Enter. And we don't have any HandleCounts that are equal to that. So, what I'll do is I'll type:

Get-Process Explorer | Select-Object HandleCount

Sometimes the HandleCount changes. So, right now, it's 2460.

So, let's repeat the command before, and we'll change from 2465 to 2460.

Get-Process | Where-Object{$_.HandleCount -eq 2460}

And now you can see that we've filtered by HandleCount.

So, let's take a look at some other techniques that use Where-Object to do some filtering. I showed you how you could filter based on HandleCount and based on name, but what about CPU usage? We'll look for processes with CPU usage greater than 1000. What I'm going to do is type and enter:

Get-Process | Where-Object {$_.CPU -GT 1000}

(The -GT stands for “greater than.” If you wanted “lesser than,” it would be -LT.)

So, this shows us we have two processes with a CPU load of greater than 1000.

We can also filter on multiple conditions. So, as you can see, we got two results when we checked to see which processes had a CPU load of greater than 1000. Just for the sake of demonstration, let's filter based on CPU load and process name.

If we're going to do a multi-condition property, then what we have to do is we have to put each condition in parentheses. Let's take a look at how that works:

Get-Process | Where-Object {($_.CPU -GT 1000) -and ($_.Name -eq ‘System’)}

I’ll press Enter. And so, we get one result. That one result is the one process that meets our criteria. It has a process name of ‘System,’ and it has a CPU load greater than 1000.

So, that's how you filter on multiple conditions.

Using ForEach Loops To Perform Actions on Individual Items in a Collection

One last thing that I want to show you is ForEach loops.

Now, ForEach loops can be used in a variety of different ways, but they're really useful because they can go through an object and look at one item within that object at a time. For example, when we typed Get-Process, each process was an item within the list of processes. We could use a ForEach loop to take action on each process.

But I'm going to switch things up just a little bit. And what I'm going to do is I'm going to create a variable. I'll call this $Colors. And I'm going to set this equal to a few different colors.

$Colors=(‘Red’, ‘Green’, ‘Blue’, ‘Yellow’)

I'll press Enter. What we've done is created a variable called Colors that contains four different colors.

So, if I type $Colors, PowerShell shows me the contents of that variable – in this case, red, green, blue, and yellow, and each one is displayed on a separate line because each one of these colors is a separate item. And just to prove that these are indeed separate items, I'm going to type $Colors just like I did before, but I'm going to append .count.

$Colors.count

And that's going to show me how many individual items. So, we have four colors, and then PowerShell shows us the number four, indicating that each color is indeed being treated as a separate item.

Now that we have a collection of items, let's look at how a ForEach loop works. So, I'm creating a loop that's going to look at each color within my list of colors. That's what this line does.

What I'm going to do is I'm going to type:

ForEach($Color in $Colors){Write-Host $Color}

*Right after ForEach, notice that I'm using $Color, not $Colors, which is the variable that I declared a moment ago. $Color is a brand-new variable. I could call this anything that I wanted. I'm just going with Color for the sake of clarity.

*Within the braces, I tell PowerShell what action to take. We could do absolutely anything that we want here, but just in the interest of keeping things simple, I'm just going to output the caller name, so I’m going to type Write-Host. Write-Host is the PowerShell cmdlet for displaying information on the screen.

When I press Enter, it's going to write that color by name on the screen. And you can see that it does that.

Now, obviously, this isn't all that exciting. The output looks the same as when I just typed the $Colors variable name. If I were to do that right now, it looks exactly like what I just did.

Just to kind of underscore the idea that we truly are dealing with each item individually, let's go ahead and add one more thing to the mix. So, I'm going to repeat the command that I just typed. So, here's the command that we used a moment ago. But what I'm going to do is change the Write-Host command a little bit. Rather than ending it with Write-Host $Color, I'm going to add a -ForegroundColor $Color:

ForEach($Color in $Colors){Write-Host $Color -ForegroundColor $Color}

So, assuming that I haven't made any typos, what this command should do is display the list of colors just as it did before, but we're going to display each color name in the color that it's indicated. So, I'll go ahead, and press Enter.

Red
Green
Blue
Yellow

Now you can see Red is displayed in red, Green is displayed in green, Blue is displayed in blue, and Yellow is displayed in yellow. So, we truly are taking action on each item in this list.

Conclusion

So, that's just a quick rundown of some of the filtering options that exist in PowerShell for pipeline objects. There are many, many, many more techniques than what I've been able to cover in this video. But this was just designed to give you a taste of some of the things that are possible to help you get started.

So, with that said, I'm Brian Posey and thanks for watching.

About the author

Brien Posey headshotBrien Posey is a bestselling technology author, speaker, and 21x Microsoft MVP. In addition to his ongoing work in IT, Posey has trained as a commercial astronaut candidate in preparation to fly on a mission to study polar mesospheric clouds from space..
Hide comments

Comments

  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Publish