Skip to main content

PowerShell Basics - The Pipeline

Author by Mitchell Grande

Continuing with our PowerShell basics series, the next important concept is the pipeline.  The pipeline refers to how PowerShell passes the result of one command to the input of another command.  Unlike other scripting languages that pass raw text, PowerShell passes full objects along the pipeline.  Remembering back to the previous topic, PowerShell objects are full representations of some type of item, like a file or user account.  By passing full objects down the pipeline, it is relatively easy to create fairly complex workflows.

Using the Pipeline

To use the pipeline in PowerShell, simply chain two or more commands together, separating them with the "pipe" character: |.  For example, this command will get the file named "myfile.txt" and pass that to the Copy-Item command to copy it to another location:

Get-Item "myfile.txt" | Copy-Item -Destination C:\Temp

You can use more than two commands to achieve more complex processes.  For example, this command will rename myfile.txt to myfile2.txt, and then copy it to another location:

Get-Item "myfile.txt" | Rename-Item -NewName "myfile2.txt" -PassThru | Copy-Item -Destination C:\temp\

Nearly all "Get" commands can be piped to another command to take action on the object that you are retrieving.  Some common examples of this are:

Get-ADUser jdoe | Set-ADUser -Enabled $false #Disable the AD user named jdoe

Get-Process explorer.exe | Stop-Process #Stop the process named explorer.exe

Get-Mailbox jdoe | Set-Mailbox -AuditEnabled $true #Enable auditing for the jdoe mailbox

Multiple Objects

One of the great features of the pipeline is the ability to act on multiple objects seamlessly.  Each of the examples in the previous section worked on a single object, but you can do the same with multiple results just as easily.  This command will copy all txt files in the current folder to another folder:

Get-Item "*.txt" | Copy-Item -Destination C:\Temp

The next command will disable all the users that haven't logged in since 5/1/2018.  This command will work no matter how many users are found.  It could be 0, 1, 2, or 100.

Get-ADUser -Filter {LastLogonDate -lt "2018-05-01"} | Set-ADUser -Enabled $false

Building Commands

As you've seen above, the most common use of the pipeline is to build commands in a "get" then "change" workflow.  We use the first command to get the object(s) we want to change and then use the second command to make the changes we desire.  The same pattern will hold up while writing commands on your own.  Before using a Remove-Item command to delete files, you will likely want to review the affected files first.  If you're writing the code to do this, you would first run the Get-Item command until you're retrieving the exact files you want to delete.  Then, simply pipe those results to the Remove-Item command to delete them.  Here's how that would look in code.

First, write and tweak the Get-ChildItem command to find only the files you want to remove.  This example will find all *.log files from before 6/1/2018 in C:\Temp.

Get-ChildItem -Path C:\Temp | Where-Object { $_.LastWriteTime -lt "2018-06-01" -and $_.Name -like "*.log"}

Then, after this command is returning the exact files you want to remove, simply pipe it to the Remove-Item command.  This will remove all of the files found in the previous command.

Get-ChildItem -Path C:\Temp | Where-Object { $_.LastWriteTime -lt "2018-06-01" -and $_.Name -like "*.log"} | Remove-Item

For our next post, we'll be looking at the Select-Object and Where-Object commands like we see in the last example above.  These commands are the main tools for filtering and managing sets of multiple objects.


Mitchell Grande

Systems Engineer

Tags in this Article