PowerShell has a unique variable called the pipeline variable ($_ or $PSItem). Due to PowerShell's ability to pipe entire objects from one command to another, it needed a way to represent that object that was traversing the pipeline.

When one PowerShell command pipes something to another command, that command can send an object. An object can be of any type. That object then has a set of methods and properties attached to it. We can reference those methods and properties on a standalone object by creating the object, assigning it to a variable, and then referencing its properties and methods that way.

For example, the Get-Item cmdlet returns a System.IO.DirectoryInfo object when querying a directory.

Get-Item -Path 'C:\Windows' | Get-Member
Using Get Item to query a directory

Using Get Item to query a directory

This object then has lots of different methods and properties we can reference. I could call methods on this object or reference its properties.

PS C:\> $windowsDir.GetFiles()

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a-h--        6/14/2017   8:24 AM          12292 .DS_Store
-a-h--        6/14/2017   8:22 AM           4096 ._.DS_Store
-a----        7/22/2017   6:00 PM          64512 bfsvc.exe
-a--s-         4/8/2018   3:16 AM          67584 bootstat.dat
-a----        10/8/2016   1:15 PM         232960 DfsrAdmin.exe
-a----         8/9/2017  10:28 AM           1315 DfsrAdmin.exe.config

PS C:\> $windowsDir.LastWriteTime

Sunday, April 8, 2018 6:00:19 AM

Simple enough, right? But, what if I'm using a cmdlet like Get-ChildItem, which enumerates lots of directories at once? It'd be crazy to assign variables like $dir1, $dir2, and $dir3 to all of them. We need a more dynamic way to represent them. We need a single variable that represents each directory object upon processing it. We need the pipeline variable!

Using the Get-ChildItem example, let's say I want to find all directories in the C:\Windows folder using Get-ChildItem -Path C:\Windows\ -Directory. This command returns a few dozen directories. If we'd assign this output to a variable, it'd be an array of objects, not just a single object. Instead, I can pipe all of those objects, one at a time, from Get-ChildItem to ForEach-Object and reference the pipeline variable.

The pipeline variable ($_ or $PSItem) represents each object upon processing it. You can see below that I can reference the Name property for every directory processed using $_.Name.

PS C:\> Get-ChildItem -Path C:\Windows\ -Directory | ForEach-Object { $_.Name  }

With the pipeline variable, we can reference any method and property. The variable will always be of the same type as the object coming from the previous command. You can see below that if you pipe the pipeline variable itself to Get-Member, it returns the same System.IO.DirectoryInfo object type as Get-Item.

PS C:\> Get-ChildItem -Path C:\Windows\ -Directory | ForEach-Object { $PSItem | Get-member  } | Select-Object -First 1

   TypeName: System.IO.DirectoryInfo

You'll see the pipeline variable most often used in commands that need to reference or perform some specific action on each object processed. Another example is using the Select-Object cmdlet's calculated properties. This allows the scripter to manipulate the output returned by referencing objects from the pipeline.

For example, instead of using ForEach-Object to return only the directory names, I could use a calculated property to create a DirectoryName property on the fly and assign the directory names to that.

Subscribe to 4sysops newsletter!

PS C:\> Get-ChildItem -Path C:\Windows\ -Directory | Select-Object -Property @{ Name = 'DirectoryName'; Expression = { $_.Name } }


Thus, we can use the pipeline variable in many different scenarios. In what scenarios do you use the pipeline variable?

  1. carlos 5 years ago

    Hey, thanks for the post. one fast question.

    How i can take the object from the first comands of the pipeline? for example imagine i do thisç

    Get-mailboxdatabase | get-mailbox | get-mailboxstatistics | select object “objectfrom get-mailbox” “objectfrom get-mailboxstatistics” “object from mailboxdatabase”

    Dont know if i explain well. and sorry for my english, not native speaker here.


  2. Simon 4 years ago

    I am interested in the answer to this too.

    When we pipeline two or more commands together we end up with only the properties of the last command in the chain.


    command1 | command2 | fl

    results in;

    Command2 property 1 : 

    Command2 property 2 : 

    Command2 property 3 :


    Very often we need properties from the preceding commands to build the desired output.

    The way I usually do this is to assign the output of each command to a variable then tie the two together at the end.

    $variable1 = command1

    $variable2 = command1 | command2

    To be able to use this we need a common field between the two commands to link them together or more usually a foreach loop. This is massively inefficient.

    So to reiterate Carlos' question I think what we are looking for is something along the lines of

    command1 | command2 | ft






  3. Luc Fullenwarth 4 years ago


    You can do this with the -OutVariable parameter (when it has been implemented).

    Get-Something -OutVariable FirstResult | Get-SomethingElse -OutVariable SecondResult | Get-AnotherThing

    This command line displays the result of the third cmdlet.

    However, $FirstResult stores the result of the first cmdlet and $SecondResult stores the result of the second cmdlet.

    Please note that when you use the -OutVariable parameter you must omit the $ sign.

    This does not work

    Get-Something -OutVariable $FirstResult | Get-SomethingElse -OutVariable $SecondResult | Get-AnotherThing


  4. Martin 4 years ago

    In recent powershell versions, there's also specific parameter called -PipelineVariable (alias pv). See:

    Get-Help about_commonParameters
    • Swapnil Kambli 4 years ago

      True. PipelineVariable introduced in PowerShell 4.0 helps further optimize the code for parameter management.

Leave a reply

Your email address will not be published.


© 4sysops 2006 - 2023


Please ask IT administration questions in the forums. Any other messages are welcome.


Log in with your credentials


Forgot your details?

Create Account