Streams

When running from bash all 6 streams can get merged to STDOUT

STDERR (apparently can go to STDERR sometimes)

PowerShell Streams Reference

Overview

PowerShell has 7 streams: 1 input stream and 6 output streams. This allows fine-grained control over different types of output.

The Streams

StreamNumberCmdletPurpose
stdin-Read-Host, pipelineInput to commands
Success1Write-OutputNormal output (stdout)
Error2Write-ErrorError messages (stderr)
Warning3Write-WarningWarning messages
Verbose4Write-VerboseDetailed information
Debug5Write-DebugDebug information
Information6Write-Host, Write-InformationUser messages

Writing to Streams

# Success (default, goes to pipeline)
Write-Output "Normal output"
"This too"  # Implicit Write-Output

# Error
Write-Error "Something failed"

# Warning
Write-Warning "Proceed with caution"

# Verbose (must enable with -Verbose or preference)
Write-Verbose "Detailed info" -Verbose

# Debug (must enable with -Debug or preference)
Write-Debug "Debug info" -Debug

# Information (displayed to user, not piped by default)
Write-Host "Hello user"
Write-Information "Info message" -InformationAction Continue

Redirecting Streams

Basic Redirection

# Redirect to file
command 1> output.txt    # Success to file
command 2> errors.txt    # Errors to file
command 3> warnings.txt  # Warnings to file

# Suppress streams
command 2>$null          # Discard errors
command 3>$null          # Discard warnings

# Redirect all streams
command *> everything.txt

Merging Streams

# Merge error into success (stderr → stdout)
command 2>&1

# Merge warning into error (warning → stderr)
command 3>&2

# Merge all into success
command *>&1

Multiple Redirections

# Separate outputs
Get-Process 1> output.txt 2> errors.txt 3> warnings.txt

# Clean output: suppress errors and warnings
Get-Process 2>$null 3>$null

# Send warnings to stderr, keep stdout clean
command 3>&2 > output.txt

Controlling Stream Behavior

Preference Variables

$ErrorActionPreference = "Stop"          # Treat errors as terminating
$WarningPreference = "SilentlyContinue"  # Hide warnings
$VerbosePreference = "Continue"          # Show verbose messages
$DebugPreference = "Continue"            # Show debug messages
$InformationPreference = "Continue"      # Show information messages

Per-Command Parameters

Get-Process -ErrorAction Stop
Get-Process -WarningAction SilentlyContinue
Get-Process -Verbose
Get-Process -Debug
Get-Process -InformationAction Continue

Common Patterns

Suppress Warnings

# Using parameter
ConvertTo-Json -WarningAction SilentlyContinue

# Using redirection
ConvertTo-Json 3>$null

Capture All Output

# Capture success and error
$result = command 2>&1

# Capture everything
$all = command *>&1

Clean Pipeline Output

# Only success goes through pipeline
Get-Process 2>$null 3>$null | Where-Object {$_.CPU -gt 10}

# Errors and warnings to stderr, data to stdout
Get-Process 2>&2 3>&2 | ConvertTo-Json

Separate Good and Bad Output

# Save output and errors separately
Get-ChildItem -Recurse 1> files.txt 2> access_errors.txt

Practical Examples

Example 1: Clean JSON Output

# Problem: Warnings pollute output
Get-Process | ConvertTo-Json -Depth 1 | jq

# Solution: Redirect warnings to stderr
Get-Process | ConvertTo-Json -Depth 1 3>&2 | jq

# Or suppress warnings
Get-Process | ConvertTo-Json -Depth 1 -WarningAction SilentlyContinue | jq

Example 2: Debugging Function

function Process-Data {
    param($Data)
    
    Write-Verbose "Starting processing..." -Verbose
    Write-Debug "Data: $Data" -Debug
    
    if ($Data -eq $null) {
        Write-Error "Data is null"
        return
    }
    
    Write-Warning "This might take a while"
    Write-Output "Result: $Data"
}

# Run with all streams visible
Process-Data "test" -Verbose -Debug

# Run with clean output
Process-Data "test" 3>$null 4>$null 5>$null

Example 3: From Bash

# Redirect PowerShell streams in bash
pwsh -c 'Get-Process | ConvertTo-Json 3>&2' > output.json 2> warnings.txt

# Suppress warnings in bash
pwsh -c 'Get-Process | ConvertTo-Json 3>$null' > output.json

Key Differences from Bash

FeatureBashPowerShell
Total streams3 (stdin, stdout, stderr)7 (stdin + 6 output)
Stream numbers0, 1, 21-6 (plus stdin)
GranularityBasicFine-grained
Warning streamNo (uses stderr)Yes (separate)
Verbose/DebugNo (manual)Yes (built-in)

Quick Reference

# Redirecting
command 1> file   # stdout to file
command 2> file   # stderr to file
command 3> file   # warnings to file
command *> file   # all to file

# Merging
command 2>&1      # stderr → stdout
command 3>&2      # warning → stderr
command *>&1      # all → stdout

# Suppressing
command 2>$null   # discard errors
command 3>$null   # discard warnings
command *>$null   # discard all

# Parameters
-ErrorAction SilentlyContinue
-WarningAction SilentlyContinue
-Verbose
-Debug

Best Practices

  1. Use Write-Output for data that goes through the pipeline
  2. Use Write-Host for user messages that shouldn't be piped
  3. Use Write-Error for errors, not throw (unless terminating)
  4. Use Write-Warning for non-critical issues
  5. Use Write-Verbose for detailed logging (enable with -Verbose)
  6. Use Write-Debug for troubleshooting (enable with -Debug)
  7. Redirect streams (3>&2) rather than suppressing when you need logs
  8. Suppress streams (3>$null) when you want clean output

Backlinks