Quick Links

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:

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.

image

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?

image

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.

notepad C:\Windows\System32\WindowsPowerShell\v1.0\DotNetTypes.format.ps1xml

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.

image

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
image

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.

Get-Service | Format-Wide

image

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.

Get-Service | Format-Wide -Property DisplayName -Column 6

image

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.

image

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.

Get-Process | Format-List

image

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.

Get-Process | Format-List –Property *

image

Alternatively, you can select just the properties you want.

Get-Process | Format-List –Property name,id

image

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.

Get-Process | Format-Table name,id –AutoSize

image

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.

Get-Service | Where-Object {$_.Status -eq "Running"}

image

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!