Thursday, July 26, 2007

PowerShell, $input vs. process

So, what is the difference between a script (Add-TimeStampA.ps1) with this content -
$input | % { "$(get-date -f HH:mm:ss) $(out-string -inp $_)"}

versus this (Add-TimeStampB.ps1)? -
process {"$(get-date -f HH:mm:ss) $(out-string -inp $_)"}

The best way to show it is to try it. First a simple demo -

PS> "hi" | .\Add-TimestampA.ps1
10:08:05 hi
PS> "hi" | .\Add-TimestampB.ps1
10:08:06 hi

The same.
Let's try a loop -

PS> "a","b","c" | .\Add-TimestampA.ps1
10:09:01 a
10:09:01 b
10:09:01 c
PS> "a","b","c" | .\Add-TimestampB.ps1
10:09:03 a
10:09:03 b
10:09:03 c

Still the same.
Let's try it with a loop that takes some time!

PS> "a","b","c" | % { start-sleep -s 3; $_ } | .\Add-TimestampA.ps1
10:10:11 a
10:10:11 b
10:10:11 c
PS> "a","b","c" | % { start-sleep -s 3; $_ } | .\Add-TimestampB.ps1
10:10:21 a
10:10:24 b
10:10:27 c

Did you notice the difference? With Add-TimeStampA all input comes at once and the timestamp is applied at the same time. With Add-TimeStampB, the output is stamped as it is generated.

The explanation is this: The version with $input, stalls the pipeline and waits for all input from the previous command before continuing (just like Sort-Object). The version with process, handles the input as it comes dripping down the pipeline.

You could also see it this way: $input turns the script into a blocking function whereas process makes the script behave like a filter (use get-help about_function for more).

No comments: