Have Your Output and Variable Too

There’s a relatively useful suggestion floating around on Twitter on how to save results of PowerShell command to a variable and see the results at the same time.

PS C:\> ($data=get-process)

I’ll admit this is a clever technique: you get the results from Get-Process written to the pipeline AND a variable $data. The other way, and frankly I think a better way, is to use Tee-Object. Usually we use Tee-Object to save output to a file and still write the results to the pipeline.

PS C:\> get-process | tee -variable data

To me, this is much more straightforward and I don’t have to remember a punctuation trick. I’ve also found that using Tee-Object is also better performing. I’ve tried a number of tests and they all seem to verify that Tee-Object is faster. Here’s one test:

PS C:\Users\Jeff> measure-command {($a=dir $env:temp -rec)}

Days : 0
Hours : 0
Minutes : 0
Seconds : 0
Milliseconds : 468
Ticks : 4686037
TotalDays : 5.42365393518518E-06
TotalHours : 0.000130167694444444
TotalMinutes : 0.00781006166666667
TotalSeconds : 0.4686037
TotalMilliseconds : 468.6037

PS C:\Users\Jeff> measure-command {dir $env:temp -rec | tee -Variable a}

Days : 0
Hours : 0
Minutes : 0
Seconds : 0
Milliseconds : 158
Ticks : 1583448
TotalDays : 1.83269444444444E-06
TotalHours : 4.39846666666667E-05
TotalMinutes : 0.00263908
TotalSeconds : 0.1583448
TotalMilliseconds : 158.3448

I get the same result with both commands but you can see that Tee-Object is significantly faster.

Using the parentheses trick is handy and especially useful in the interactive console. Personally, I’ll probably stick to using Tee-Object and certainly in a script using Tee-Object is easier to follow and understand.

5 thoughts on “Have Your Output and Variable Too

    • Interesting. I happen to test on v3 in Windows 8 preview on my netbook. I’ll have to retest in v2.

  1. Hi Jeff. Considered using the common parameter “-OutVariable” to get the same effect?

    The trick is to feed the name of a variable without the $ prefix. If the variable doesn’t exist, -OutVariable will create it. Check it out:

    Get-Process -OutVariable procs

    Is equivalent to:

    Get-Process | tee -Variable procs

    Output still goes to the pipeline, and is simultaneously captured by the variable $procs.

    The performance is QUITE a bit better with -OutVariable:

    PS C:\Users\Kfreiheit> measure-command {(Get-Process -OutVariable procs)}

    Days : 0
    Hours : 0
    Minutes : 0
    Seconds : 0
    Milliseconds : 2
    Ticks : 27367
    TotalDays : 3.16747685185185E-08
    TotalHours : 7.60194444444444E-07
    TotalMinutes : 4.56116666666667E-05
    TotalSeconds : 0.0027367
    TotalMilliseconds : 2.7367

    PS C:\Users\Kfreiheit> measure-command {(Get-Process | tee -Variable procs)}

    Days : 0
    Hours : 0
    Minutes : 0
    Seconds : 0
    Milliseconds : 96
    Ticks : 962522
    TotalDays : 1.11403009259259E-06
    TotalHours : 2.67367222222222E-05
    TotalMinutes : 0.00160420333333333
    TotalSeconds : 0.0962522
    TotalMilliseconds : 96.2522

    • I should have thought to mention Outvariable as well. It certainly has some advantages. But keep in mind that it only works for cmdlets and advanced functions with cmdlet binding which should cover 90% of what someone might do. For everything else we would need to resort to the parens trick or Tee object.

Comments are closed.