powershellterminalwindows-consoletee

Can you redirect Tee-Object to standard out?


I am writing a script and I want to pass the values but also see them displayed

Get-Content data.txt | Tee-Object | data_processor.exe

But Tee-Object always requests a file and I just want to see it on the screen.


Solution

  • You can output to a variable instead of a file:

    Get-Content data.txt | Tee-Object -Variable data | data_processor.exe
    $data  # Output
    

    This passes content to "data_processor.exe" and stores it in variable $data. Data will be shown only when the .exe has finished.

    Use ForEach-Object to examine output of Get-Content before each line is being send to the .exe:

    Get-Content data.txt | ForEach-Object {
        Write-Host $_   # Output line to console
        $_              # Forward line to next command in chain 
    } | data_processor.exe
    

    This pattern could be made more succinct and reusable, by writing a small filter function:

    Filter Write-HostAndForward {
        Write-Host $_   # Output line to console
        $_              # Forward line to next command in chain    
    }
    

    Now we can write:

    Get-Content data.txt | Write-HostAndForward | data_processor.exe
    

    Remarks:

    While Write-HostAndForward works for simple input, like strings received from Get-Content, for complex objects it typically doesn't produce the same output as we normally see in the console. That is because Write-Host simply converts the input to string using the .ToString() method, which skips PowerShells rich formatting system.

    You might be tempted to simply replace Write-Host by Out-Host, but as mklement0 explains, it would format the input objects individually, which will produce a header for each object for table-formatted output. To avoid that, mklement0's answer shows different ways to produce the expected formatted output.