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:
Write-Output "This is stream 1 (Success)"
Write-Error "This is stream 2 (Error)" -ErrorAction Continue
Write-Warning "This is stream 3 (Warning)"./streams-demo.ps1This 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.
Get-Process -Name "pwsh" > "$PSScriptRoot\processes.txt"
Get-Date >> "$PSScriptRoot\processes.txt"where:
>creates (or overwrites)processes.txtwith the output ofGet-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:
Get-Item "C:\InvalidPath\File.txt" 2> "$PSScriptRoot\errors.log"
Remove-Item "C:\MissingFile.txt" 2>> "$PSScriptRoot\errors.log"Get-ChildItem -Path "C:\Missing" 2> errors.txtGet-Content errors.txtGet-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:
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:
$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>&1routes 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.
pwsh ./merge-error-stream.ps1 | Select-Object -First 3RecordType Content
---------- -------
Error Cannot find path 'C:\InvalidFolder' because it does not exist.
SuccessItem C:\Windows\System32\drivers\etc
SuccessItem C:\Windows\System32\drivers\en-USMerging into a File
Get-ChildItem -Path "C:\Missing" 2>&1 > combined.txtwhere:
2>&1redirects errors into the success stream first.- The subsequent
> combined.txtthen captures both streams together into a single file.
Get-Content combined.txtGet-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.
Write-Output "Success message"
Write-Warning "Warning message"
Write-Error "Error message" -ErrorAction Continue./all-streams-demo.ps1 *> full-log.txt
Get-Content full-log.txtSuccess message
WARNING: Warning message
Write-Error: Error messagewhere *> is the simplest way to capture a script's complete console output (every message type) into one log file.
./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:
[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-Outputand[PSCustomObject]send objects to Stream 1.Write-Warningemits a warning to Stream 3.Write-Verbosesends background progress messages to Stream 4.Write-Erroremits 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:
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:
Get-Content -Path "$PSScriptRoot\results.log"Node assessment initiated.
Hostname AuditPass CheckedAt
-------- --------- ---------
WORKSTATION-01 False 2026-10-24 20:45:10Get-Content -Path "$PSScriptRoot\errors.log"run-environment-audit.ps1: Failed to reach DNS gateway at 192.0.2.1.Get-Content -Path "$PSScriptRoot\diagnostics.log"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>&1before 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-Hostbypasses all streams: useWrite-Information(Stream 6) if the message must be redirectable. - Prefer
Out-File -Encoding utf8inside scripts for guaranteed, version-independent encoding. - Avoid
>for structured data: useExport-CsvorConvertTo-Jsonto preserve object structure. - Use explicit stream numbers (
1>,2>) in scripts for clarity, even when the default applies.