PowerShell Basics: Formatting
How to use the Format-Wide, Format-Table, and Format-List cmdlets
September 27, 2013
When you run a command in Windows PowerShell, objects are written to the pipeline and possibly even passed from one cmdlet or function to the next. If there are any objects left in the pipeline at the end, PowerShell displays them. But sometimes the display is less than optimal. To overcome this, you'll need to take control of PowerShell's formatting system.
How Formatting Works
Without getting too deep into the technical details, here's how PowerShell handles formatting: At the end of the pipeline, PowerShell looks at the remaining objects and determines their types. PowerShell then looks through a set of XML configuration files for instructions on how to format each specific object type. It might see a default display for a table or list. If so, PowerShell passes the objects to the appropriate formatting cmdlet, which displays the results on screen. Or PowerShell might only find a default list of properties. Depending on the number of properties, PowerShell will decide if it needs a table or a list and again call the appropriate formatting cmdlet. As a last resort, if no instructions are found, PowerShell will display all object properties.
You can override this formatting system by explicitly running the formatting cmdlets. The formatting cmdlets that you're most likely to use are Format-Wide, Format-Table, and Format-List.
How to Use the Format-Wide Cmdlet
The Format-Wide cmdlet, which has an alias of fw, will display a single property in wide format. In the Windows Cmd.exe shell, you might have used a command like dir /w to see a wide directory listing. Format-Wide provides the same type of display for any object type. For example, the following command displays the results from the Get-Process cmdlet in wide format:
Get-Process | Format-Wide
You can see the results in Figure 1.
Figure 1: Displaying Results in Wide Format
With Format-Wide, most object types have a defined default property, which is usually a name. However, you can specify a different property. For example, instead of displaying service names in wide format, you can display the DisplayName property in wide format by using the command:
Get-Service | Where-Object {$_.status -eq 'running'} | Format-Wide -Property DisplayName
Format-Wide usually does a good job of maximizing the display, but you can fine tune it if you want. For example, when Get-Process was piped to Format-Wide in the first example, the results were in two columns, as shown in Figure 1. You can force Format-Wide to use more columns using the -Column parameter:
Get-Process | Format-Wide -Column 3
Now the results are in three columns, as Figure 2 shows.
Figure 2: Displaying Results in Three Columns
You can force Format-Wide to squeeze as much as it can into the display using the -AutoSize parameter. For example, the following command returns services that start with the letter m, maximizing the amount of data displayed:
Get-Service m* | fw -AutoSize
Notice that in this instance, I'm using the alias fw. Figure 3 shows the results.
Figure 3: Maximizing the Amount of Data Displayed
You might want to combine the auto-size feature with the grouping feature of Format-Wide. When using the -GroupBy parameter, PowerShell will format the output in groups based on a specified property. But be careful. Look at this command:
Get-Service | fw -GroupBy Status -AutoSize
You might think that this command will get the services, then display them in wide format grouped by the Status property. But look at the result in Figure 4.
Figure 4: Getting Unexpected Results When Grouping Results
It's probably not what you expected. PowerShell took the incoming service objects and formatted them as they arrived. This problem is easily solved by sorting first with the Sort-Object cmdlet, which has an alias of sort:
Get-Service w* | sort Status | fw -GroupBy Status -AutoSize
This command returns only those services starting with the letter w so that you can see all the results, which are shown in Figure 5. In the results, notice that the stopped services are displayed using five columns and the running services are displayed using only four columns. Auto-sizing results will vary depending on the length of each property value.
Figure 5: Getting the Expected Results When Grouping Results
The -GroupBy parameter is supported by all the formatting cmdlets. The -AutoSize parameter is supported by Format-Wide as well as Format-Table, which I'll discuss next.
How to Use the Format-Table Cmdlet
As its name suggests, the Format-Table cmdlet, which has an alias of ft, formats output as a table. Formatting results as a table is commonly done by administrators, and PowerShell even does it by default in some cases. For example, running
Get-Process
produces the same results as running
Get-Process | Format-Table
As I mentioned in the "How Formatting Works" section, PowerShell uses a set of configuration files to determine what to display and how. Some object types have predefined formatted outputs. In this case, the configuration files tell PowerShell to format the process objects as a table. In theory, this means that you don't need to include the Format-Table cmdlet when using Get-Process if you want the results formatted in a table. However, how many times have you run a command only to find that the output isn't exactly optimal? Take, for example, the following command that uses the Select-Object cmdlet, which has an alias of select, to return the ID, Name, and WorkingSet (WS) properties:
Get-Process | Format-Table
As you can see in Figure 6, the output is in a table, but the columns' size and placement aren't ideal.
Figure 6: Selecting Properties Without Any Formatting
PowerShell did the best job it could, but selecting properties isn't the same as formatting them. You can help by piping the results to the Format-Table cmdlet with the -AutoSize parameter to force PowerShell to auto-size the results in the table:
Get-Process | select ID,Name,WS | Format-Table -AutoSize
As Figure 7 shows, the output is nicer.
Figure 7: Selecting and Formatting the Properties
If you know from the beginning that you want the output to be formatted in a table, you can skip the Select-Object step and simply specify the properties when calling Format-Table:
Get-Process | Format-Table ID,Name,WS -AutoSize
This will produce the same output. If all you want to do is look at the results, this is perfectly fine. But there's something about formatting that trips up many PowerShell beginners, which I'll discuss in a bit.
Besides -AutoSize, another Format-Table parameter that you'll probably use often is the -View parameter. A view is an alternative layout. Using the -View parameter tells PowerShell to use one of the alternative displays. For example, if you run the following command, you'll get a different set of properties automatically grouped by the PriorityClass property:
Get-Process | sort PriorityClass | ft -View Priority
Notice that I used the alias ft, which you'll probably end up using a lot. Also notice that I sorted first to improve the display output, just as I did when grouping earlier with Format-Wide. Figure 8 should give you an idea of what to expect. You might get errors because some processes like Idle and System are protected. You can ignore the errors.
Figure 8: Using an Alternative Display
Here's another example I'll leave for you to try:
Get-Process | sort StartTime | ft -View StartTime
Like the previous command, this command might generate errors because some processes won't have start times.
Discovering alternative views takes a little detective work. First, you use the Get-Member cmdlet to find the object type. In the case of the last Get-Process example, you'd run:
Get-Process | Get-Member
The results show that the object type is System.Diagnostics.Process. Then, you run the following command to expand the definition property:
Get-FormatData System.Diagnostics.Process | Select -ExpandProperty FormatViewDefinition
In the results shown in Figure 9, the Name column contains the view names. The Control column gives you a hint about what formatting cmdlet to use to see the corresponding view. Note that you won't necessarily see views for every object type, so you might still need to do a lot of manual testing.
Figure 9: Discovering the Different Views Available
How to Use the Format-List Cmdlet
Another common way to format output is a list. You can force PowerShell to output a list by using the Format-List cmdlet, which has an alias of fl. For example, if you run the following command, you'll find that PowerShell formats the results as a table:
Get-Process | select ID,Name,WS,VM
If you'd rather have the output formatted as a list, you can pipe the results to Format-List like this:
Get-Process | select ID,Name,WS,VM | Format-List
Figure 10 shows the results.
Figure 10: Formatting Output as a List
Like the other formatting cmdlets, Format-List lets you specify one or more properties to display. You can even use wildcards, including the asterisk (*) to get all the properties.
Although piping Get-Process output to Get-Member can help you discover an object's properties, sometimes it helps even more to see the values for those properties. A great way to use Format-List is to get a single object and list all its properties and their values:
Get-Process winword | fl *
With output like that in Figure 11, you'll have a better idea of what the properties mean and can begin devising a more detailed command.
Figure 11: Listing an Object's Properties and Their Values
As with Format-Table, Format-List might have different views defined for different object types. Take, for example, the command:
Get-Service | fl
The results in Figure 12 show that PowerShell has a view defined for service objects when they're formatted as a list.
Figure 12: Discovering that PowerShell has a View Defined for Service Objects When They're Formatted as a List
To learn about the views available, you can try using Get-FormatData and looking for ListControl in the Control column. Alternatively, you can experiment by running commands piped to Format-Table and Format-List. You might be surprised at what you discover.
Format at the End
You might have noticed that in all my examples, the formatting cmdlet was at the end of the command. In classes and forums, I often see PowerShell novices try to do something like this:
Get-ChildItem C:scripts*.ps1 | ft name,length,LastWriteTime,CreationTime | Export-CSV C:workfiles.csv
But when they look at the .csv file, it's gibberish. Here's another command that will fail, but at least there's an error message that explains why:
Get-ChildItem C:scripts*.ps1 | ft name,length,LastWriteTime,CreationTime | sort Length
Figure 13 shows the error message. Admittedly, this message isn't easy to understand, so I'll explain what it means. When you invoke one of the formatting cmdlets, it creates a different type of object and passes it back to PowerShell. So, in the failed command, Format-Table wrote formatting directive objects to the pipeline, which PowerShell then tried to sort on the Length property. But at this point, the pipeline is no longer working with file objects, so the command fails. This gets confusing because if you replace Format-Table with Select-Object, it works.
Figure 13: Receiving an Error Message
The rule of thumb is that formatting should be the last part of a PowerShell command. As long as you don't try to do anything after a formatting cmdlet, you shouldn't run into any problems. The assumption is that you're formatting to make the results easier to read and nothing else. However, there's one exception. You can pipe any formatted output to any of the Out cmdlets, such as Out-File or Out-Printer. For example, the following command pipes the Format-Table output to Out-File:
Get-ChildItem C:scripts*.ps1 | ft name,length,LastWriteTime,CreationTime | Out-File C:workscripts.txt
PowerShell will take the same output you'd see on screen and send it to the file.
Give Them a Try
I recommend that you take a few minutes to read the Help files and look at the examples for the formatting cmdlets, then give them a try. Don't be afraid to experiment. Once you understand how formatting works, you'll be bending PowerShell to your will in no time.
About the Author
You May Also Like