Posey's Tips & Tricks

How To Create Pipeline Chain Operators in PowerShell 7

If you have spent much time working with PowerShell, you are probably familiar with the PowerShell pipeline. Represented by the pipe symbol (found on the backslash key on most keyboards), the pipeline allows one command's output to be treated as input for another command.

For instance, suppose you wanted to see what version of PowerShell was installed on your computer. You could get the version number by using this command:

Get-Host | Select-Object version

The Get-Host cmdlet retrieves various pieces of information about the current PowerShell session such as the session name, version number and instance ID. The output from that command is then fed into the Select-Object cmdlet, which filters the output, displaying only the version number. You can see what this looks like in Figure 1.

Figure 1: This is the way that the PowerShell pipeline normally works.

PowerShell version 7 introduces a new feature called a pipeline chain. Rather than simply using the pipeline in the manner I demonstrated above, you can actually use the pipeline as a sort of If-Then statement. Let me show you how this works.

To begin with, I will repeat the same command I showed you a moment ago, but this time I will use two pipe symbols instead of just one. Here is what the command looks like:

Get-Host || Select-Object Version

If you look at Figure 2 below, you can see that this command produces output that is very different from what you saw in the previous figure. In fact, the command's output is identical to what you would see if you ran the Get-Host cmdlet by itself, without the pipes or the Select-Object cmdlet. So what happened?

[Click on image for larger view.] Figure 2: The Select-Object cmdlet is being ignored.

Remember when I said that the pipeline chain works like an If-Then statement? The pipeline chain (at least, as I have used it here) is essentially telling PowerShell that if the first command executes successfully, then it should ignore the second command. In this case, the Get-Host cmdlet did exactly what it was supposed to do, so PowerShell ignored everything after the double pipe symbol.

If the Get-Host cmdlet had failed, then PowerShell would have executed the Select-Object cmdlet, but that would have produced an error because if the Get-Host cmdlet fails, then there are no objects to select. Since that doesn't work, let me show you this another way.

This time I will use the Write-Error cmdlet as the first cmdlet to be executed. The Write-Error cmdlet causes PowerShell to produce an error message. I will use the Write-Host cmdlet as the second cmdlet. The Write-Host cmdlet simply displays text on the screen. Here is the command that I am using:

Write-Error 'My error message' || Write-Host "The second command is executing"

If you look at Figure 3, you can see that because the first command has failed (produced an error), the second command is allowed to run.

[Click on image for larger view.] Figure 3: The first command produces an error, so the second command is allowed to run.

That's great, but what if you want to switch things up so that the second command only runs if the first command succeeds? To do this, all you have to do is to replace the two pipe symbols with two ampersands. Let's try the same command that I just ran, but this time I will use ampersands instead of pipe symbols. Here is what the command looks like:

Write-Error 'My error message' && Write-Host "The second command is executing"

As you can see in Figure 4, the first half of the command produced an error message just as it was intended to do. Because this error occurred, the second half of the command was not allowed to run.

[Click on image for larger view.] Figure 4: An error occurred in the first half of the command, so the second half did not run.

Before I wrap up, there is one very important thing that you need to know about pipeline chaining. A pipeline chain does not work like a regular pipeline. As previously mentioned, a regular pipeline takes one command's output and uses it as input for the next command. When a pipeline chain is used, the two commands are treated as individual entities. To show you what I mean, take a look at this command:

Get-Host && Select-Object version

When I run this command, the Get-Host portion succeeds, which allows the Select-Object portion to run. However, nothing has been passed to the Select-Object cmdlet because the commands exist independently of one another and no pipeline relationship exists. As such, the output is the same as if I had run the Get-Host cmdlet by itself. You can see what this looks like in Figure 5.

[Click on image for larger view.] Figure 5: The two commands do not share a normal pipeline relationship.

About the Author

Brien Posey is a 22-time Microsoft MVP with decades of IT experience. As a freelance writer, Posey has written thousands of articles and contributed to several dozen books on a wide variety of IT topics. Prior to going freelance, Posey was a CIO for a national chain of hospitals and health care facilities. He has also served as a network administrator for some of the country's largest insurance companies and for the Department of Defense at Fort Knox. In addition to his continued work in IT, Posey has spent the last several years actively training as a commercial scientist-astronaut candidate in preparation to fly on a mission to study polar mesospheric clouds from space. You can follow his spaceflight training on his Web site.


comments powered by Disqus

Subscribe on YouTube