Question:
In Powershell, we can combine the standard output stream with any other stream and then redirect (write) the result to the same file.
Examples:
1 2 3 |
Powershell -File "C:\myscript.ps1" 2>&1> "C:\log.txt" Powershell -File "C:\myscript.ps1" 3>&2>&1> "C:\log.txt" |
Suppose I use Write-Error and Write-Warning statements in myscript.ps1 and I want to write only the errors and the warnings to the same file.
Note: if I am not mistaken, 1 is the output stream, 2 is the error stream and 3 the warning stream.
My first logical try was then to use 3>&2> – if combining 1 and 2 works, why would not 3 and 2 ? See below:
1 2 |
Powershell -File "C:\myscript.ps1" 3>&2> "C:\log.txt" |
However, 3>&2> does not work as a valid redirect operator.
I could get around trying:
Powershell -File "C:\myscript.ps1" 3>"C:\warninglog.txt" 2>"C:\errorlog.txt"
but I really want to write to the same file.
If I try to run:
1 2 |
Powershell -File "C:\myscript.ps1" 3>"C:\log.txt" 2>"C:\log.txt" |
it seems the error stream (2) never gets written to log.txt because file is locked by the warning stream.
Is there a way to combine two (or more) output streams into a single stream and redirect the result to the same file ?
Answer:
The verbose, warning, and debug streams are merged into STDOUT when you run PowerShell scripts via
1 2 |
powershell -File "C:\myscript.ps1" |
so you can’t redirect them separately anymore. Only the error stream is different, since it seems to go to both STDOUT and STDERR, where it can be redirected by 1>
as well as 2>
.
Demonstration:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
C:\>type test.ps1 $DebugPreference = "Continue" $VerbosePreference = "Continue" Write-Output "Output message" Write-Error "Error message" Write-Verbose "Verbose message" Write-Warning "Warning message" Write-Debug "Debug message" C:\>powershell -File .\test.ps1 Output message C:\test.ps1 : Error message + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,test.ps1 VERBOSE: Verbose message WARNING: Warning message DEBUG: Debug message C:\>powershell -File .\test.ps1 2>nul 3>nul 4>nul 5>nul Output message VERBOSE: Verbose message WARNING: Warning message DEBUG: Debug message C:\>powershell -File .\test.ps1 1>nul C:\>_ |
If you want to redirect the verbose, warning, or debug stream separately you must use
-Command
instead of -File
and do the redirection within PowerShell:
1 2 3 |
C:\>powershell -Command ".\test.ps1 2>$null 3>$null 5>$null" Output message VERBOSE: Verbose message |
However, while in CMD you can redirect any handle to any other handle (
3>&2
, 1>&5
, …), PowerShell redirection only supports redirection to either a file (3>C:\out.txt
) or the success output stream (3>&1
). Trying to redirect to any other stream will throw an error:
1 2 3 4 5 6 7 |
C:\>powershell -Command ".\test.ps1 2>out.txt 3>&2" At line:1 char:22 + .\test.ps1 2>out.txt 3>&2 + ~~~~ The '3>&2' operator is reserved for future use. + CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException + FullyQualifiedErrorId : RedirectionNotSupported |
as will redirecting different streams to the same file:
1 2 3 4 5 6 7 8 |
C:\>powershell -Command ".\test.ps1 2>out.txt 3>>out.txt" out-file : The process cannot access the file 'C:\out.txt' because it is being used by another process. At line:1 char:1 + .\test.ps1 2>out.txt 3>>out.txt + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : OpenError: (:) [Out-File], IOException + FullyQualifiedErrorId : FileOpenFailure,Microsoft.PowerShell.Commands.OutFileCommand |
If merging warning and success output is an option for you, you could do something like this:
1 2 |
powershell -Command ".\test.ps1 >out.txt 3>&1 2>error.log" |
or like this:
1 2 |
powershell -Command ".\test.ps1 >out.txt 3>&1 2>&1" |
or (redirecting all streams) like this:
1 2 |
powershell -Command ".\test.ps1 *>out.txt" |
Otherwise the only option I see is to redirect to different files:
1 2 |
powershell -Command ".\test.ps1 3>warning.log 2>error.log" |