Powershell redirect stderr and stdout to two different places Powershell redirect stderr and stdout to two different places powershell powershell

Powershell redirect stderr and stdout to two different places


Joining stdout and stderr output streams works like PetSerAl commented, though the syntax is not the most intuitive.

The weirdish syntax of 2>&1 means that stderr (stream 2) is to be added into the stdout (stream 1). As this is not actually what you are after, try adapting the other example from the MS page to Powershell:

Or, you can redirect the output to one place, and the errors to another.

dir file.xxx > output.msg 2> output.err

Thus,

$ret = myCommand 2> errors.log

should send errors in a log file and non-errors in the $ret variable.


A comprehensive explanation in about_Redirection MSDN article.

A Minimal, Complete, and Verifiable example (stdout to pipe):

PS D:\PShell> -1,5,0,2| ForEach-Object { 15/$_ } 2>"$env:temp\err.txt" | Write-Output-1537.5PS D:\PShell> Get-Content "$env:temp\err.txt"Attempted to divide by zero.At line:1 char:28+ -1,5,0,2| ForEach-Object { 15/$_ } 2>"$env:temp\err.txt" | Write-Outpu ...+                            ~~~~~    + CategoryInfo          : NotSpecified: (:) [], RuntimeException    + FullyQualifiedErrorId : RuntimeExceptionPS D:\PShell> 

Another example (stdout to object):

PS D:\PShell> $x = -1,5,0,2| ForEach-Object { 15/$_} 2>"$env:temp\err.txt"PS D:\PShell> $x-1537.5


clsfunction GetAnsVal {    param([Parameter(Mandatory=$true, ValueFromPipeline=$true)][System.Object[]][AllowEmptyString()]$Output,          [Parameter(Mandatory=$false, ValueFromPipeline=$true)][System.String]$firstEncNew="UTF-8",          [Parameter(Mandatory=$false, ValueFromPipeline=$true)][System.String]$secondEncNew="CP866"    )    function ConvertTo-Encoding ([string]$From, [string]$To){#"UTF-8" "CP866" "ASCII" "windows-1251"        Begin{            $encFrom = [System.Text.Encoding]::GetEncoding($from)            $encTo = [System.Text.Encoding]::GetEncoding($to)        }        Process{            $Text=($_).ToString()            $bytes = $encTo.GetBytes($Text)            $bytes = [System.Text.Encoding]::Convert($encFrom, $encTo, $bytes)            $encTo.GetString($bytes)        }    }    $all = New-Object System.Collections.Generic.List[System.Object];    $exception = New-Object System.Collections.Generic.List[System.Object];    $stderr = New-Object System.Collections.Generic.List[System.Object];    $stdout = New-Object System.Collections.Generic.List[System.Object]    $i = 0;$Output | % {        if ($_ -ne $null){            if ($_.GetType().FullName -ne 'System.Management.Automation.ErrorRecord'){                if ($_.Exception.message -ne $null){$Temp=$_.Exception.message | ConvertTo-Encoding $firstEncNew $secondEncNew;$all.Add($Temp);$exception.Add($Temp)}                elseif ($_ -ne $null){$Temp=$_ | ConvertTo-Encoding $firstEncNew $secondEncNew;$all.Add($Temp);$stdout.Add($Temp)}            } else {                #if (MyNonTerminatingError.Exception is AccessDeniedException)                $Temp=$_.Exception.message | ConvertTo-Encoding $firstEncNew $secondEncNew;                $all.Add($Temp);$stderr.Add($Temp)            }            }    $i++    }    [hashtable]$return = @{}    $return.Meta0=$all;$return.Meta1=$exception;$return.Meta2=$stderr;$return.Meta3=$stdout;    return $return}Add-Type -AssemblyName System.Windows.Forms;& C:\Windows\System32\curl.exe 'api.ipify.org/?format=plain' 2>&1 | set-variable Output;$r = & GetAnsVal $Output$Meta2=""foreach ($el in $r.Meta2){    $Meta2+=$el}$Meta2=($Meta2 -split "[`r`n]") -join "`n"$Meta2=($Meta2 -split "[`n]{2,}") -join "`n"[Console]::Write("stderr:`n");[Console]::Write($Meta2);[Console]::Write("`n");$Meta3=""foreach ($el in $r.Meta3){    $Meta3+=$el}$Meta3=($Meta3 -split "[`r`n]") -join "`n"$Meta3=($Meta3 -split "[`n]{2,}") -join "`n"[Console]::Write("stdout:`n");[Console]::Write($Meta3);[Console]::Write("`n");