Summary: Microsoft PFE, Gary Siepser, further investigates the basics of the Windows PowerShell pipeline.
Microsoft Scripting Guy, Ed Wilson, is here. It's midweek already! Time sure flies, especially when you have a guest blogger for the week. Welcome back Gary Siepser for the third part in a series. To catch up, read:
- Back to the Basics Part 1: Learn About the PowerShell Pipeline
- Back to the Basics Part 2: Learn about the Pipeline and "Getters"
In Part 2 of this series, we looked at how you start a pipeline. In this part, we’ll see some basic and easy-to-use commands that let us manipulate that data to suit our needs.
First, let’s do a quick review of cmdlets. They are single-purpose commands that can be used together in a pipeline as building blocks for a real solution. Because most cmdlets truly are single purpose, they usually lack common functionality, such as exporting to other file formats or sorting the output. Often Get cmdlets don’t even have very rich filtering capabilities. This is intentional. We have other single-purpose cmdlets to address those needs.
Let’s also recall that the pipeline is simply a way to string commands together. The output of one command becomes the input of the next command. All of the cmdlets we are going to look at in this post were specifically designed to be used in the pipeline. As a matter of fact, if you try to start a line with these commands, they typically don’t work like you would expect. They were meant to be used in the pipeline, so we need to use them that way.
For the rest of this post, we’ll focus on four simple but key ways we need to work with our data:
The best part about the cmdlets that perform these feats is that they work with ANYTHING. They were designed to work with any objects coming through the pipeline. They even have the noun of Object to keep them generic. The big win is that you learn them once, and use them forever!
We’ll start with the simplest: Sort-Object. The Sort-Object cmdlet is so simple to use. There are really only two things to think about:
1. What you want to sort by
2. Ascending or descending sort
The latter is the easier one to talk about. If you want an ascending sort, don’t do anything. This is what the cmdlet does by default.
Now for choosing what to sort by…
Most of time, I will look at the unsorted results first to spot what property I want to sort by (or column if it’s a table). If I spot something, just use the Up arrow in the Windows PowerShell console to bring up the last command, and pipe it to the Sort-Object cmdlet. You’ll specify the property name that you want to sort by after the cmdlet.
Note Sort is command alias for Sort-Object. I am not normally a big fan of using many shortcuts in Windows PowerShell, but this is one I really like because it keeps your pipeline very readable—almost like spoken language.
Take a look at the following examples of using Sort-Object. For more help with the command, like always, check out the Help topic (Get-Help Sort-Object –ShowWindow).
If you try to use a property name that you saw (for example, the WS(K) column heading from Get-Process), and you find that something isn’t quite working as expected, there is a technique to solve your issue. This works for all the Object cmdlets we are going to cover.
The issue here is that the default view you get when you run a command can sometimes lie to us a little. There is some default formatting magic that occurs in Windows Powershell to make these default views look better (beauty is always in the eye of the beholder, of course). This magic can make it a little harder to look at column headings and use them with your cmdlets. Always try them first, but if it fails, Get-Member is your savior.
Get-Member is an investigative cmdlet that will show us what we are working with. Down the road, when you really start geeking-out with Windows Powershell and objects, Get-Member is truly a great asset. Even in the beginning stages of our Windows Powershell lives, we can get value from it without diving in too deeply. Pipe whatever you are working with to the Get-Member cmdlet, and it will show you a list of all the real properties for the object. For now, ignore anything that doesn’t have the word property in its MemberType column.
There is some truncation in the previous example to show a few different types of members without making you scroll too far.
Armed with Get-Member, you can now choose what property you are going to sort by. As I mentioned earlier, this applies to not only all the Object cmdlets in this post, but all across Windows Powershell. Get-Member will show you what you are really working with instead of the more “user-friendly” default views we normally see.
Now that we can sort our data, let’s move on to simplifying what you are working with. Select-Object is, in my opinion, the Swiss Army knife of Windows Powershell. It can really manipulate your objects a lot. To keep things simple right now, we’ll look at how it can strip down your objects to only the properties you want to deal with. This is really easy.
Follow the Select-Object (the alias is Select) cmdlet with a comma-separated list of the properties you want to keep. There is a really cool side effect of doing this. After you have simplified your objects, the default formatting I referred to earlier has really neat behavior. If you strip down an object to four or less properties, you will see them as a table. If you strip it down to five or more properties, you will get a list.
This is cool because default formatting isn’t normally dynamic. It’s a logical choice that Windows PowerShell makes for you, and I see a lot of folks using it for that reason. In Part 5 of this series, we will look at outputting your data. Using Select-Object reduces some need to directly control the output and formatting by dynamically choosing them for you.
Take a look at how this looks:
You can see that in the first example, there were only four properties, so we saw a table. The second example had five properties, and Windows PowerShell automatically generated a list. Also, because of the width of the command, I took advantage of line-continuation in Windows PowerShell by hitting ENTER after the pipeline character. If you are working in the ISE Console, press Shift + ENTER.
Select-Object can do so much more than this, but we want to keep things simple in this post and series. To see more, check out the Help for Select-Object (Get-Help Select-Object –ShowWindow). The examples in the Help show many different options.
Next, we’ll use Measure-Object to get a count of objects in the pipeline. (The alias is Measure. Are we seeing a trend with the alias names?) This is something I use all the time! There are several ways in Windows PowerShell to get this count, but I love just piping to Measure.
Measure-Object can get several other calculations for numeric properties such as sum and average. It can also analyze text for lines and characters, and analyze words for string objects and properties. For more information, check the Help file (Get-Help Measure-Object –ShowWindow).
Take a look at these examples for counting objects:
Lastly, we’ll look at some simple examples of filtering objects. We filter objects in the pipeline by using the Where-Object cmdlet. (Surprise, we have the alias: Where.) Using Where-Object can get a little advanced, and in this post, we are going to look at only using the simplified syntax. This easier-to-use and easier-to-look-at syntax was introduced in Windows PowerShell 3.0, and it covers a good majority of the filtering that I see with Where-Object.
To filter objects, we need to tell Where-Object what property we want to test, how we want to test it, and what value we are testing against. That may sound a little complicated, but it’s actually pretty straight-forward. Like all the other cmdlets, though, looking at the Help file will clear up all the ways that the cmdlet works (Get-Help Where-Object –ShowWindow).
Take a look at these examples of filtering by using Where-Object to see what I am talking about. I love that they are fairly high-level language and quite readable.
I can’t help but read these two example lines and think to myself that any IT admin is going to understand what is happening, even if they have never ever heard of Windows PowerShell. I like intuitive, and this is definitely it.
Before I close this post, I want to show one more example where we bring a few of these cmdlets together at the same time into a more complex, but still easy-to-understand pipeline:
Now that, my friends, is piping.
In Part 4, we will look at a few even cooler things that we can do with our data in the pipeline, for example, grouping by similar values, teeing our objects in two directions, and the original non-simplified syntax for Where-Object.
Thank you, Gary, for sharing your time and knowledge.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at firstname.lastname@example.org, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy