Skip to content

PowerShell Redirection Operators

How to use PowerShell's numbered streams (1-6) with redirection operators (>, 2>, *>&1) to route success output, errors, warnings, and diagnostics to files or merge them into the pipeline for advanced logging and troubleshooting.

Redirection operators route text output from PowerShell commands, expressions, and scripts to physical files, or redirect data between internal runtime streams. While traditional command shells like Bash or Command Prompt (cmd.exe) support only standard output and standard error, PowerShell features a multi-stream architecture with six distinct output channels that can be redirected individually, appended, or merged.

PowerShell extends the traditional shell redirection concept (>, >>) with a full set of numbered streams, allowing precise control over where success output, errors, warnings, and other message types are routed.

PowerShell Output Streams (1 through 6)

PowerShell separates engine communications into six numbered streams. Redirection operators reference these streams by their numeric ID:

Stream ID Stream Name Emitting Cmdlet Default Destination Description
1 Success Write-Output / expressions Console Host Standard pipeline data objects and returned values.
2 Error Write-Error / runtime errors Console Host (Red) Terminating and non-terminating error records.
3 Warning Write-Warning Console Host (Yellow) Warning messages and deprecation notices.
4 Verbose Write-Verbose Suppressed (unless -Verbose) Detailed background status and diagnostic traces.
5 Debug Write-Debug Suppressed (unless -Debug) Interactive troubleshooting and debugging details.
6 Information Write-Information / Write-Host Console Host Host presentation messages and informational tags.

For example:

streams-demo.ps1powershell
Write-Output "This is stream 1 (Success)"
Write-Error "This is stream 2 (Error)" -ErrorAction Continue
Write-Warning "This is stream 3 (Warning)"
Consolepowershell
./streams-demo.ps1
Outputplaintext
This is stream 1 (Success)
Write-Error: This is stream 2 (Error)
WARNING: This is stream 3 (Warning)

Standard Redirection: > and >>

The standard redirection operators target Stream 1 (Success) by default.

  • >: Overwrites the target file. If the file exists, its contents are cleared; if it does not exist, it is created.
  • >>: Appends to the target file. If the file exists, new content is written to the end; if it does not exist, it is created.
Consolepowershell
Get-Process -Name "pwsh" > "$PSScriptRoot\processes.txt"

Get-Date >> "$PSScriptRoot\processes.txt"

where:

  • > creates (or overwrites) processes.txt with the output of Get-Process.
  • >> appends the output to the end of the existing file, without erasing its contents.

Targeted Stream Redirection: 2>, 3>, and beyond

You can redirect any specific stream by prefixing the redirection operator with the stream's numeric ID (n> or n>>).

Redirecting Errors with 2> and 2>>

To separate error messages from standard output, route Stream 2 to an independent error log:

Consolepowershell
Get-Item "C:\InvalidPath\File.txt" 2> "$PSScriptRoot\errors.log"

Remove-Item "C:\MissingFile.txt" 2>> "$PSScriptRoot\errors.log"
Consolepowershell
Get-ChildItem -Path "C:\Missing" 2> errors.txt
Consolepowershell
Get-Content errors.txt
Outputplaintext
Get-ChildItem : Cannot find path 'C:\Missing' because it does not exist.

where:

  • 2> redirects only stream 2 (Error) output to the specified file.
  • Stream 1 (Success) output, if any, would still print normally to the console.

Redirecting Diagnostic Streams (3>, 4>, 5>, 6>)

You can route warnings, verbose messages, or informational records to separate files without capturing general pipeline output:

Consolepowershell
Write-Warning "Disk capacity low" 3> "$PSScriptRoot\warnings.log"

./backup-script.ps1 -Verbose 4> "$PSScriptRoot\verbose.log"

Any of the six stream numbers can be used this way: 3> for warnings, 4> for verbose, 5> for debug, and 6> for information.

Stream Merging: 2>&1 and n>&1

The stream merging operator n>&1 redirects output from stream n directly into Stream 1 (Success).

Merging Errors into Success (2>&1)

By default, error records cannot be piped into cmdlets like Where-Object or Select-String because they reside on Stream 2. Merging Stream 2 into Stream 1 converts errors into pipeline objects alongside standard output:

merge-error-stream.ps1powershell
$Captured = Get-ChildItem "C:\InvalidFolder", "C:\Windows\System32\drivers"  2>&1

$Captured | ForEach-Object {
    if ($_ -is [System.Management.Automation.ErrorRecord]) {
        [PSCustomObject]@{
            RecordType = "Error"
            Content    = $_.Exception.Message
        }
    }
    else {
        [PSCustomObject]@{
            RecordType = "SuccessItem"
            Content    = $_.FullName
        }
    }
}

where:

  • 2>&1 routes errors from Stream 2 directly into the Stream 1 pipeline.
  • $_ -is [System.Management.Automation.ErrorRecord] checks if the object is an error or a filesystem item.
Consolepowershell
pwsh ./merge-error-stream.ps1 | Select-Object -First 3
Outputplaintext
RecordType  Content
----------  -------
Error       Cannot find path 'C:\InvalidFolder' because it does not exist.
SuccessItem C:\Windows\System32\drivers\etc
SuccessItem C:\Windows\System32\drivers\en-US

Merging into a File

Consolepowershell
Get-ChildItem -Path "C:\Missing" 2>&1 > combined.txt

where:

  • 2>&1 redirects errors into the success stream first.
  • The subsequent > combined.txt then captures both streams together into a single file.
Consolepowershell
Get-Content combined.txt
Outputplaintext
Get-ChildItem : Cannot find path 'C:\Missing' because it does not exist.

Redirecting All Streams: *>

The wildcard redirection operators *> and *>> capture all six streams simultaneously, routing standard output, errors, warnings, verbose traces, and host messages to a single file.

  • *>: Clears the destination file and captures all streams.
  • *>>: Appends output from all streams to an existing file.
  • *>&1: Merges all streams into Stream 1, allowing the entire execution output to be piped downstream.
all-streams-demo.ps1powershell
Write-Output "Success message"
Write-Warning "Warning message"
Write-Error "Error message" -ErrorAction Continue
Consolepowershell
./all-streams-demo.ps1 *> full-log.txt
Get-Content full-log.txt
Outputplaintext
Success message
WARNING: Warning message
Write-Error: Error message

where *> is the simplest way to capture a script's complete console output (every message type) into one log file.

Consolepowershell
./deploy-application.ps1 -Verbose *> "$PSScriptRoot\deployment-all.log"

Quick Reference

Syntax Effect
> file.txt Redirect stream 1 (Success) to file, overwrite
>> file.txt Redirect stream 1 (Success) to file, append
2> file.txt Redirect stream 2 (Error) to file
2>> file.txt Append stream 2 (Error) to file
3> file.txt Redirect stream 3 (Warning) to file
4> file.txt Redirect stream 4 (Verbose) to file
2>&1 Merge stream 2 (Error) into stream 1 (Success)
*>&1 Merge all streams into stream 1
*> file.txt Redirect all streams to file, overwrite
*>> file.txt Redirect all streams to file, append

Practical Example: Multi-Stream Execution Logger

The following script emits messages across multiple streams and uses redirection operators to isolate standard pipeline data from errors and diagnostic logs:

run-environment-audit.ps1powershell
[CmdletBinding()]
param ()

Write-Output "Node assessment initiated."

Write-Warning "Configuration file using legacy schema version 1.0."

Write-Verbose "Querying network interfaces for active IPv4 bindings..."

Write-Error "Failed to reach DNS gateway at 192.0.2.1."

[PSCustomObject]@{
    Hostname = $env:COMPUTERNAME
    AuditPass = $false
    CheckedAt = (Get-Date -Format "yyyy-MM-dd HH:mm:ss")
}

where:

  • Write-Output and [PSCustomObject] send objects to Stream 1.
  • Write-Warning emits a warning to Stream 3.
  • Write-Verbose sends background progress messages to Stream 4.
  • Write-Error emits a non-terminating error to Stream 2.

Invoke the script from the console, redirecting Stream 1 to results.log, Stream 2 to errors.log, and Streams 3 and 4 to diagnostics.log:

Consolepowershell
pwsh -File ./run-environment-audit.ps1 -Verbose `
    1> "$PSScriptRoot\results.log" `
    2> "$PSScriptRoot\errors.log" `
    3>> "$PSScriptRoot\diagnostics.log" `
    4>> "$PSScriptRoot\diagnostics.log"

Inspect the isolated log files created on disk:

Consolepowershell
Get-Content -Path "$PSScriptRoot\results.log"
Outputplaintext
Node assessment initiated.

Hostname       AuditPass CheckedAt
--------       --------- ---------
WORKSTATION-01     False 2026-10-24 20:45:10
Consolepowershell
Get-Content -Path "$PSScriptRoot\errors.log"
Outputplaintext
run-environment-audit.ps1: Failed to reach DNS gateway at 192.0.2.1.
Consolepowershell
Get-Content -Path "$PSScriptRoot\diagnostics.log"
Outputplaintext
WARNING: Configuration file using legacy schema version 1.0.
VERBOSE: Querying network interfaces for active IPv4 bindings...

Best Practices

  • Use 2> to isolate errors from normal output for easier troubleshooting.
  • Place 2>&1 before the destination redirect (2>&1 > file.txt) when capturing merged output.
  • Use *> for comprehensive logging when you need every stream in one place.
  • Remember that Write-Host bypasses all streams: use Write-Information (Stream 6) if the message must be redirectable.
  • Prefer Out-File -Encoding utf8 inside scripts for guaranteed, version-independent encoding.
  • Avoid > for structured data: use Export-Csv or ConvertTo-Json to preserve object structure.
  • Use explicit stream numbers (1>, 2>) in scripts for clarity, even when the default applies.
Navigation