In this edition of Geek School, we look at formatting, filtering and comparing objects in the Pipeline.
Be sure to read the previous articles in the series:
Learn How to Automate Windows with PowerShell Learning to Use Cmdlets in PowerShell Learning How to Use Objects in PowerShell
And stay tuned for the rest of the series all week.
Default Formatting
When I first started out with PowerShell, I thought everything was magic, but the truth is it just takes a little bit of time to understand what is going on underneath the hood. The same is true for the PowerShell formatting system. In fact, if you run the Get-Service cmdlet, the output generated only shows you 3 properties: Status, Name and DisplayName.
But if you pipe Get-Service to Get-Member, you see that the ServiceController objects have a lot more than just these three properties, so what is going on?
The answer lies within a hidden file that defines how most of the built-in cmdlets display their output. To get an understanding, type the following into the shell and hit enter.
If we use notepad’s Find function, we can quickly skip to the section that details the output of the Get-Service cmdlet by searching for the ServiceController type.
Suddenly, you can see that underneath the hood PowerShell is formatting any objects in the Pipeline that are of the ServiceController type and creating a table with three columns: Status, Name, and DisplayName. But what if the type you are dealing with doesn’t have an entry in that file, or any other format file for that matter? Well then, it’s quite simple actually. If the object coming out of the pipeline has 5 or more properties, PowerShell displays all of the object’s properties in a list; if it has less than 5 properties, it displays them in a table.
Formatting Your Data
If you are not happy with the default formatting of an object or type, you can roll your own formatting. There are three cmdlets you need to know to do this.
Format-List Format-Table Format-Wide
Format-Wide simply takes a collection of objects and displays a single property of each object. By default, it will look for a name property; if your objects don’t contain a name property, it will use the first property of the object once the properties have been sorted alphabetically.
As you can see, it also defaults to two columns, although you can specify both which property you want to use, as well as how many columns you want to be displayed.
If something is formatted as a table by default, you can always switch it to list view by using the Format-List cmdlet. Let’s take a look at the output of the Get-Process cmdlet.
This tabular view actually suits this kind of information very well, but let’s pretend we want to view it in list form. All we really have to do is pipe it to Format-List.
As you can see there are only four items displayed in the list by default. To view all the properties of the object, you can use a wildcard character.
Alternatively, you can select just the properties you want.
Format-Table, on the other hand, takes data and turns it into a table. Since our data from Get-Process is already in the form of a table, we can use it to easily choose properties we want displayed in the table. I used the AutoSize parameter to make all the data fit onto a single screen.
Filtering and Comparing
One of the best things about using an object-based pipeline is that you can filter objects out of the pipeline at any stage using the Where-Object cmdlet.
Using where object is actually very simple. $_ represents the current pipeline object, from which you can choose a property that you want to filter on. Here, were are only keeping objects where the Status property equals Running. There are a few comparison operators you can use in the filtering script block:
eq (Equal To) neq (Not Equal To) gt (Greater Than) ge (Greater Than or Equal To) lt (Less Than) le (Less Than or Equal To) like (Wildcard String Match)
A full list and more information can be viewed in the about_comparison conceptual help file, however it does take some time getting used to the Where-Obeject syntax. That’s all for this time!