This article follows the theme of my last one: Formatting object output in PowerShell with Format.ps1xml files. Here we'll look at the built-in cmdlets Format-Custom, Format-List, Format-Table, and Format-Wide that PowerShell provides to format your output.

From my previous article, we know *.format.ps1xml files in the PowerShell installation directory ($pshome) control object formatting. PowerShell provides Format-* cmdlets that let the user change object appearance when writing them back to the console.

To see the available format cmdlets and the ones I will be discussing in this article, let's turn to Get-Command:

Get-Command -Name Format-* -Module Microsoft.PowerShell.Utility  CommandType Cmdlet

We'll look at each of these next. To start exploring the Format cmdlets, we'll look at Format-Table first. Format-Table and Format-List are the two main format cmdlets you'll use in PowerShell.

Format-Table ^

The Format-Table cmdlet formats the output into column form.

PS C:\> Get-Item -Path c:\tmp | Format-Table
    Directory: C:\
Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----       17/09/2018     12:50                tmp

PowerShell automatically defines the on-screen position of these objects. Format-Table provides the AutoSize switch to improve the display:

PS C:\> Get-Item -Path c:\tmp | Format-Table -AutoSize
    Directory: C:\
Mode          LastWriteTime Length Name
----          ------------- ------ ----
d----- 17/09/2018     12:50        tmp

Using the AutoSize switch parameter requires the formatter to process every element before returning to the screen. This prevents the smooth flow of streaming to the screen. PowerShell's default is usually good enough and is certainly worth considering when formatting larger amounts of data to the screen.

The View parameter provides an alternate table format or view. Get-Process uses the System.Diagnostics.Process type. In this example, we can pass one of following three views: process, Priority, or StartTime. The DotNetTypes.format.ps1xml formatting file defines these three views for System.Diagnostics.Process objects. Using Get-Process and searching for processes starting with w* lets us add the Priority view:

Get-Process -Name w* | Format-Table -View Priority
Using the Priority view with Get Process

Using the Priority view with Get Process

Note how it splits the processes by PriorityClass. If you want to find a view without going through the format files, an interesting trick is to add any character to the view value, and PowerShell's error system will provide the available views:

Get-Process -Name w* | Format-Table -View a
An incorrect value for views displaying the available views

An incorrect value for views displaying the available views

I've highlighted the above screenshot showing the available views to use for Get-Process (System.Diagnostics.Process). See, not all errors in PowerShell are bad!

Another switch parameter in Format-Table not used much is the HideTableHeaders parameter. HideTableHeaders does what you probably think it does—it hides the column names!

Get-Item -Path c:\tmp\* | Format-Table -HideTableHeaders
PS C:\> Get-Item -Path c:\tmp\* | Format-Table -HideTableHeaders
    Directory: C:\tmp
d-----       13/09/2018     08:52                Configuration

The property parameter for all the format cmdlets allows you to pass a hash table. Here's how:

Get-Service | Sort-Object Status |
    Format-Table -Property @{Name='Name';Expression={$_.Name};align='center'}, Status

I've piped this to Sort-Object first to make the final output nicer to view. I've kept the same details for the Name property but added a third part to the hash table for alignment. This extra step formats the text output of a column with either left, right, or center alignment. Look at the first column to see how the names are centered:

Aligning text in output to console

Aligning text in output to console

There are some overlapping parameters, GroupBy and Property, which I will discuss in the next Format cmdlet. Their usage is the same across each Format cmdlet.

Format-List ^

The Format-List cmdlet formats the output of a command as a list of properties, showing each property on a new line. This cmdlet is most useful for displaying output that has many fields.

Here's an example using Get-Item again:

Get-Item -Path c:\tmp | Format-List
Displaying objects as a list

Displaying objects as a list

Compare the difference in format and object display from Format-Table.

The Property parameter spans across all the Format cmdlets, allowing you to select which fields to return to the console, for example:

Get-Item c:\tmp | Format-List -Property FullName, LastAccessTime, Attributes
FullName       : C:\tmp
LastAccessTime : 17/09/2018 12:50:20
Attributes     : Directory

Adding an asterisk symbol to the parameter property displays all the properties. The following command returns all the properties of the c:\tmp directory:

Get-Item c:\tmp | Format-List -Property *
PSPath            : Microsoft.PowerShell.Core\FileSystem::C:\tmp
PSParentPath      : Microsoft.PowerShell.Core\FileSystem::C:\
PSChildName       : tmp
PSDrive           : C
PSProvider        : Microsoft.PowerShell.Core\FileSystem
PSIsContainer     : True
Mode              : d-----
BaseName          : tmp
Target            : {}
LinkType          :
Name              : tmp
FullName          : C:\tmp
Parent            :
Exists            : True
Root              : C:\
Extension         :
CreationTime      : 12/09/2018 16:04:25
CreationTimeUtc   : 12/09/2018 15:04:25
LastAccessTime    : 17/09/2018 12:50:20
LastAccessTimeUtc : 17/09/2018 11:50:20
LastWriteTime     : 17/09/2018 12:50:20
LastWriteTimeUtc  : 17/09/2018 11:50:20
Attributes        : Directory

The GroupBy parameter is also available for all four Format cmdlets. Using this parameter sets the output in groups based on a shared property or value. You can work with strings, expressions, and even a scriptblock to return results.

I'll demonstrate a few examples. A straightforward one to start with is adding the LastAccessTime property to group files:

Get-ChildItem c:\ | Format-List -GroupBy LastAccessTime

In some ways this is not highly useful. Most of the time each file will have a different time even if on the same date, thus returning many individual groups. What's more useful is to calculate the value to group objects by. How about grouping files by size? This example uses a scriptblock to do this:

Get-ChildItem -Path C:\Windows\ -File |
    Sort-Object length -Unique |
    Format-List -GroupBy {[int]($_.length / 1MB)} -Property Name
GroupBy return using a scriptblock

GroupBy return using a scriptblock

Let's jump to the Format-Wide cmdlet and see what it can do for us.

Format-Wide ^

As you might expect from the name of the cmdlet, Format-Wide formats the objects as a wide table that only returns a single property for each object. By this, I mean that if you used Format-Table to look at a file piped from Get-ChildItem, you would get other property information shown, such as size and LastWriteTime. With Format-Wide, you don't, giving you a simplified return.

There's not much to this Format command. The Column parameter allows you to customize how many columns you want displayed to the console:

Get-ChildItem | Format-Wide -Column 4

You still can access the parameters we've discussed for the previous format commands: Property, AutoSize, Column, GroupBy, and View.

Format-Custom ^

Our last Format cmdlet is Format-Custom. Most folks don't talk about this cmdlet much and rarely use it. But it's worth mentioning.

The Format-Custom cmdlet displays objects while retaining their basic structure. Generally, objects have a structure of more than one object. They contain objects that contain objects, which can become very verbose! If you were to use Format-Custom without the Depth parameter, you would certainly have a full screen of information! Look at the output with the Depth parameter set to 1 on a single file:

Get-Item C:\windows\System32\mmc.exe | Format-Custom -Depth 1
Depth set to 1 when using the Format Custom cmdlet

Depth set to 1 when using the Format Custom cmdlet

When using a scriptblock to return a calculated value, it adds the value to the returned object:

Get-Date | Format-Custom -Property DayOfWeek, { $_.Year -eq 2018 }
Calculated property return with Format Custom

Calculated property return with Format Custom

In this case, it gives a Boolean result.

Finally, I will touch on a parameter that again is part of the format cmdlets: DisplayError. Using an example, I'm going to try to return files last written after September 13. This is what I use (Now I know this is wrong, but it is for demo purposes!):

Get-Item -Path c:\tmp\* | Format-Custom -Property Name, { $_.LastWriteTime -ge '13/09/2018' }
Expected information with no input

Expected information with no input

I'm expecting to see either a true or false value for my calculated property, but there's nothing. Now I can add the DisplayError parameter to debug this:

Get-Item -Path c:\tmp\* | Format-Custom -Property Name, { $_.LastWriteTime -ge '13/09/2018' } -DisplayError
Screen output after using the DisplayError switch parameter

Screen output after using the DisplayError switch parameter

The DisplayError switch parameter informs me that what I wrote for the calculated property is not correct and causes an error.

Correcting this now returns what I expected to see originally:

Get-Item -Path c:\tmp\* | Format-Custom -Property Name, { $_.LastWriteTime.ToShortDateString() -eq '13/09/2018' }
Correcting the error for a date time query

Correcting the error for a date time query

In times of need, it's nice to know how DisplayError works, but you probably won't work with this parameter much.

Subscribe to 4sysops newsletter!

Summary ^

This has been quite a thorough look into the formatting cmdlets PowerShell provides. You should not use Format commands as best practices inside your functions but as part of a pipeline. In this way, the cmdlets let you present your objects to the console in a more readable fashion.


Leave a reply

Please enclose code in pre tags

Your email address will not be published. Required fields are marked *


© 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