Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

In PowerShell, what's the difference between the operators "( )" and "|", such as `Write-Output (Get-Process)` and `Get-Process | Wirte-Output`?

I’m a novice in PowerShell.

Recently I encountered a problem about how to cascade commands or functions. I’ve found 2 ways:

  • CMD_B (CMD_A ($x))
  • $x | CMD_A | CMD_B

But, what’s the difference between the above 2 ways?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

For example, the results of Write-Output (Get-Process) and Get-Process | Wirte-Output look the same. Are there different details hidden?

I’ve searched the doc about grouping-operator () and Pipeline operator |, and find:

Piping grouped expressions

When used as the first segment of a pipeline, wrapping a command or expression in parentheses invariably causes enumeration of the expression result. If the parentheses wrap a command, it’s run to completion with all output collected in memory before the results are sent through the pipeline.

Grouping an expression before piping also ensures that subsequent object-by-object processing can’t interfere with the enumeration the command uses to produce its output.

But I don’t quite understand it. Maybe it’s because I lack the basic knowledge of pipelines.

Thanks in advance.

>Solution :

Start from the base that Write-Output (Get-Process) is the same as storing the output from Get-Process in a variable and passing it as argument to Write-Output. When you use (...) the expression must be evaluated first, before the subsequent command receives that output, this can mean for example higher memory consumption.

# can be considered the same as `Write-Output (Get-Process)`
$tmp = Get-Process
Write-Output $tmp
$tmp = $null

With the pipeline instead what you have is One-at-a-time processing, the subsequent command receives and processes one item at a time as soon as the preceding in pipeline starts outputting.

This comparison between (...) and pipelines is very easy to see if you add a bit of delay between each object outputted:

function Test-ProcessingFunction {
    param(
        [Parameter(ValueFromPipeline)]
        [int[]] $int
    )

    process {
        foreach ($i in $int) {
            "Processing $i"
        }
    }
}

$rangeDelayed = {
    0..10 | ForEach-Object { Start-Sleep -Milliseconds 200; $_ }
}

# nothing happens until `$rangeDelayed` finishes
Test-ProcessingFunction (& $rangeDelayed)
# as soon as `$rangeDelayed` outputs, it gets processed
& $rangeDelayed | Test-ProcessingFunction
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading