Executive Summary:

Windows PowerShell provides far more power and flexibility than traditional Windows command shells, such as cmd.exe. To help you take advantage of that power, this six-article series explains how to use PowerShell to perform various tasks. In this lesson, you’ll learn how to link cmdlets into a pipeline to create PowerShell statements. You’ll also learn how to format and sort output from those statements.


In “PowerShell 101, Lesson 1” (February 2008, InstantDoc ID 97742), I introduced you to the concept of cmdlets and how to run basic PowerShell commands. I also showed you how to use aliases and how to use PowerShell’s Get- cmdlets to get help when creating commands. For example, you can use the Get-ChildItem cmdlet to retrieve a list of items in a folder or the Get-Content cmdlet to retrieve the content of a text file. With cmdlets and their parameters, you can run a wide variety commands that display system information or carry out tasks.

However, a cmdlet alone might not always provide the full functionality you require. For this reason, PowerShell lets you create pipelines that link cmdlets together to carry out complex operations and refine the system information you retrieve. In this lesson, you’ll learn how to link cmdlets into a pipeline to create PowerShell statements. You’ll also learn how to format and sort statement output.

Implementing a Pipeline
A PowerShell pipeline is a series of cmdlets that pass objects from one cmdlet to the next. Each cmdlet generates an object and passes it down the pipeline, where it is received by the next cmdlet. The receiving cmdlet uses that object as input and generates its own output as an object. You connect cmdlets into a pipeline by using the pipe (|) operator.

Pipelining in PowerShell is different from pipelining in other command shell environments, such as the Windows command shell. In traditional environments, a command’s results are returned as a single result set, which means that the entire result set must be generated before any information is passed down the pipeline. The first result is returned at the same time as the last result. In PowerShell, however, the results are streamed through the pipeline. As soon as a command returns a result, it passes it down the pipeline, and that result is immediately available to the next command in the pipeline.

Let’s look at an example that will help you understand how a pipeline works. If you run the cmdlet

Get-Service

you’ll receive a list of the services installed your system, similar to the list in Figure 1. Notice that the cmdlet returns the status, name, and display name of each service. Suppose you want to retrieve a list of running services only. You can pipe the output from the Get- Service cmdlet to the Where-Object cmdlet, which filters the output based on the specified criteria, as shown in the statement

Get-Service |
 Where-Object \{$_.status -eq ‘running’\}

As you can see, you use a pipe operator to connect the two cmdlets. The Get-Service cmdlet generates an object that contains the servicerelated information. The object is passed down the pipeline to the Where-Object cmdlet. The Where-Object cmdlet receives the object and uses the information as input. The Where-Object cmdlet filters the information based on the Status property value. Notice that the Where-Object cmdlet includes an expression enclosed in braces (\{ \}). If the expression evaluates to true, the Where-Object passes that object down the pipeline and filters out any other object.

In this case, the Where-Object expression states that the Status property value must be equal to (specified by the -eq operator) the string running. Status is one of the properties available to the object generated by the Get- Service cmdlet. When an object is passed down the pipeline, you can access its properties, as I’ve done in the Where-Object expression. To access a property in the pipeline in this manner, you use the $_ built-in variable. This variable holds the current object within the pipeline each time the Where-Object cmdlet loops through the pipeline results. You can then reference the object’s properties, as in $_.Status. The output now looks similar to that in Figure 2. (You’ll learn more about the Where-Object cmdlet, object properties, and operators in later lessons.)

Note that you’d typically enter the statement just given on one line in the Power- Shell console window. However, column widths in the magazine force us to print this statement on more than one line. Also note in Figure 2 the >> character sequence at the beginning of some of the lines in the command. This character sequence constitutes a multiline prompt. For information about when you’d want to enter a statement on multiple lines in the PowerShell console window and how to properly do so.

Now suppose you want to list only the display name of each running service. You can pipe the output of the Where-Object cmdlet to the Select-Object cmdlet:

Get-Service |
where \{$_.status -eq ‘running’\} |    
select displayname

In this statement, the Select-Object cmdlet receives the object from the Where-Object cmdlet. In this case, the statement uses the where alias to reference the Where-Object cmdlet and the select alias to reference the Select-Object cmdlet. In the select cmdlet, you specify the name of the property (or properties) that you want to display. For this example, I’ve specified the displayname property. The statement will now output results similar to those in Figure 3.

The key to using pipelines is to remember that you’re always working with objects. Each cmdlet generates an object that the next cmdlet in the pipeline receives. Even the final cmdlet generates an object that outputs the statement results. As you progress through the lessons, you’ll learn how to use those objects and their properties to refine your PowerShell statements.

Formatting Statement Output
By default, PowerShell formats a statement’s output based on the type of data in that output. For example, the following statement returns data about the PowerShell process:

Get-Process powershell

Continue to page 2

In this case, PowerShell displays the output from this command in a table, as shown in Figure 4. If you don’t want the output in this default format, you can pipe the statement output to a format cmdlet. PowerShell supports four cmdlets that format output: The Format-

  • Table cmdlet displays data in a table (Figure 4). This is the default format for most cmdlets, so you often don’t need to specify it.
  • The Format-List cmdlet displays data in a list.
  • The Format-Wide cmdlet displays data in a wide table that includes only one property value for each item.
  • The Format-Custom cmdlet displays data in a custom format, based on stored configuration information in a .ps1xml format file. You can use the Update- FormatData cmdlet to update a format file. (A discussion of the Update-Format- Data cmdlet and format files is beyond the scope of these lessons. See Power- Shell’s “Update-FormatData” Help file for more information.)

To change the format of the output from the preceding statement, you can pipe it to the Format-List cmdlet:

Get-Process powershell |
Format-List

Now your results will be similar to those in Figure 5. Notice that the list format displays only a subset of the information displayed in the table format. The information displayed differs between formats. PowerShell determines how to format the results based on object type. In other words, the format type, layout, and properties returned are specific to the type of object. For example, the results returned by the Get-ChildItem cmdlet when retrieving file system information will be different from the results returned when retrieving information about the registry because they’re two different types of objects, even though the same cmdlet is used. PowerShell uses a set of complex XML format (.ps1xml) files to determine how to display the results.

Controlling Statement Output
When you execute a statement, PowerShell applies the default format to the output and sends that output to the console window, unless you override this behavior by using one the four format cmdlets I just described. However, you can also control where to send that output. PowerShell provides six cmdlets for controlling output:

  • The Out-Host cmdlet sends output to the PowerShell console. This is the default output cmdlet, so you don’t need to specify it.
  • The Out-Default cmdlet sends output to the default formatting cmdlet. In addition, Out-Default delegates the outputting process to the Out-Host cmdlet. You don’t need to specify the Out-Default cmdlet.
  • The Out-File cmdlet sends output to a specified file.
  • The Out-Null cmdlet deletes output and doesn’t send it to the PowerShell console.
  • The Out-Printer cmdlet sends output to a printer.
  • The Out-String cmdlet converts the pipeline object to an array of strings. You can find additional information about each cmdlet in the PowerShell Help files.

To control a statement’s output, add the output cmdlet at the end of your pipeline. For example, the following statement formats the PowerShell process information into a list, then sends that list to the C:\SysInfo\ps.txt file:

Get-Process powershell |
Format-List |
Out-File C:\SysInfo\ps.txt

When you send output to a file, PowerShell saves the content to the file but doesn’t display it in the console. You can use the Out-File cmdlet to send output to any type of file that makes sense. For example, you wouldn’t want to send text to a .bmp file. Although this wouldn’t throw an error, you wouldn’t be able to view anything when you opened the file.

The Out- File cmdlet lets you choose whether to append the output to the file or replace the existing content with the output. By default, it replaces any existing content. To append the output, you need to add the -append switch to the Out-File cmdlet:

Get-Process powershell |
Format-List |
Out-File C:\SysInfo\ps.txt `
-append

Sorting Statement Output
In addition to formatting output, you’ll often find that you’ll want to sort output. To sort output, you use the Sort-Object cmdlet. This cmdlet takes the input objects from the pipeline and sorts them based on the criteria you define. As I mentioned previously, Power- Shell streams the results down the pipeline from one command to the next. However, when you sort data, the Sort-Object cmdlet waits until it has all the results (objects) and then sorts them. This effectively stops the streaming process until everything is sorted. For a small result set, this isn’t a problem, but it could impact performance when retrieving large amounts of data.

Still, the Sort-Object cmdlet can be a handy tool. For example, suppose you want to retrieve a list of the items in the C:\Windows folder. You can use the Get- ChildItem cmdlet in a statement such as

 dir c:\windows |
where \{$_.length -gt 500000\} |
sort -property length
-descending

This statement passes the output object from the Get-ChildItem cmdlet (referenced by the dir alias) to the Where-Object cmdlet (referenced by the where alias). The Where-Object cmdlet specifies that the length must be greater than (specified by -gt) 500,000 bytes. The results are then passed down the pipeline. When the Sort- Object cmdlet (referenced by the sort alias) has all the objects, it sorts them based on the defined criteria.

In this case, the Sort-Object cmdlet first specifies that the sorting should be based on the Length property. The -descending switch indicates that the results should be sorted in descending order, as shown in Figure 6, page 61. If you don’t specify the -descending switch, the results are sorted in ascending order. In addition, you can specify more than one property (separated by commas) on which to base the sort order. PowerShell sorts the data first by the first property specified, then by the second, and so on.

Moving Forward
As this lesson demonstrates, the PowerShell pipeline is a powerful feature that lets you combine multiple cmdlets to perform a series of successive operations on one or more objects. You can pipe together multiple cmdlets into a statement, format the output from that statement, specify where to place the output, and even sort the outputted information. In the lessons to follow, you’ll learn how to enhance your statements even further so you can take full advantage of PowerShell’s pipeline capabilities.