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.
Fabulous information. I am already using the examples to produce useful work.
The teaching style is very user friendly, Thank you very much
The article information is very easy to follow. Thank you very much.