Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redirect warning and error stream to the same file

Tags:

powershell

I try to redirect warning and error stream to one file, and verbose and debug stream to another one, but PowerShell does not let me do so.

When I try to redirect using the & syntax, I get this error:

.\test-streams.ps1 -Debug -Verbose 1> test-streams.log 2> test-streams.err 3>&2
At line:1 char:76
+ ... eams.ps1 -Debug -Verbose 1> test-streams.log 2> test-streams.err 3>&2
+                                                                      ~~~~
The '3>&2' operator is reserved for future use.
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException

and when I try to give the same file I get this error:

.\test-streams.ps1 -Debug -Verbose 1> test-streams.log 2> test-streams.err 3> test-streams.err
out-file : The process cannot access the file 'test-streams.err' because it is being used by another process.
At line:1 char:1
+ .\test-streams.ps1 -Debug -Verbose 1> test-streams.log 2> test-stream ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OpenError: (:) [Out-File], IOException
    + FullyQualifiedErrorId : FileOpenFailure,Microsoft.PowerShell.Commands.OutFileCommand````
    + FullyQualifiedErrorId : RedirectionNotSupported

The same errors appear when I try with 4> file.txt 5>&4 or 4> file.txt 5> file.txt

The only combination which does not raise an error is >&1 but all goes into the very same file and that's not what I'm looking for.

Did I miss something? Or is it impossible?

Context:

PSVersion                      5.1.14393.8244
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.14393.8244
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
like image 830
Peyre Avatar asked Oct 24 '25 14:10

Peyre


1 Answers

Unfortunately you can only redirect streams to Success (&1) or to a file, this is described in the about_Redirection documentation. You could workaround this with some work, below example redirects all streams to success (*>&1) and sends them to the pipeline where you can determine, using a hash table in this case, if the incoming input should be redirected to a file or not.

This approach isn't the most efficient one because we're appending to a file (-Append), this means that for every input object that should be redirected, the destination file stream is being opened, appended to and closed. There are also ways to workaround this by using for example a StreamWriter or a Steppable Pipeline for each file however the answer would increase in complexity.

# a scriptblock to simulate a ps1 file
$testScript = {
    Write-Warning 'warn'
    Write-Error 'err'
    Write-Debug 'dbg' -Debug
    Write-Verbose 'verb' -Verbose
    'success output'
}

# Key: input type / Value: destination file path
$redirectiontable = @{
    [System.Management.Automation.WarningRecord] = 'warnAndErr.txt'
    [System.Management.Automation.ErrorRecord]   = 'warnAndErr.txt'
    [System.Management.Automation.DebugRecord]   = 'dbgAndVerb.txt'
    [System.Management.Automation.VerboseRecord] = 'dbgAndVerb.txt'
}

# redirect all streams to success and send to pipeline
& $testScript *>&1 | ForEach-Object {
    # if the input type exists in the redirection table, get the path
    if ($path = $redirectiontable[$_.GetType()]) {
        # append to corresponding file
        $_ | Out-File $path -Append
        # and go to next iteration
        return
    }

    # else, send to pipeline
    $_
}
like image 162
Santiago Squarzon Avatar answered Oct 26 '25 05:10

Santiago Squarzon



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!