cbsch.no


Powershell Pipelines

powershell

Powershell pipelines are in essence a replacement for loops. They can also be used to manipulate single objects.

Example

Foreach

$list = 1..5
$result = @()
foreach ($element in $list) {
    $result += $element * 2
}

Pipeline

$list = 1..5
$result = $list | % { $_ * 2 }

% is an alias for the cmdlet ForEach-Object.

In both these cases the value of $result will be @(2, 4, 6, 8, 10)

@() is the Powershell syntax for declaring an array

Pipeline execution

Every element on the left side of the pipeline will be processed by the expression on the right side of the pipeline

<input> | <process>

Pipelines can also be chained, so that the output of each pipe is sent to the next

<input> | <process-first> | <process-second>

An important thing to note is that all the pipelines will execute at the same time. Each element will be passed through the entire pipeline chain before the next element is processed. That means that this expression will be equivalent to a single loop, and not two loops

1..5 | % {
    Write-Host "Pipeline 1 processing $_"
    $_ # Pass the object to the next pipe
} | % {
    Write-Host "Pipeline 2 processing $_"
}

One might think that this will be equivalent to this:

$list = 1..5
foreach ($obj in $list) {
    Write-Host "Pipeline 1 processing $obj"
}
foreach ($obj in $list) {
    Write-Host "Pipeline 2 processing $obj"
}

But it will be equivalent to this:

foreach ($obj in 1..5) {
    Write-Host "Pipeline 1 processing $obj"
    Write-Host "Pipeline 2 processing $obj"
}

This applies to most cmdlets, but there may be exceptions. Some cmdlets will by their nature need to process the entire input before they can output a result. An example of this is the Sort-Object cmdlet.

1..5 |
    % { Write-Host "Pipeline 1 processing $_"; $_ } |
    % { Write-Host "Pipeline 2 processing $_"; $_ } |
    Sort-Object | # Sort-Object needs to read the entire pipeline before it starts outputting results
    % { Write-Host "Pipeline 3 processing $_"}