關於重定向

簡短描述

說明如何將PowerShell的輸出重新導向至文字檔。

完整描述

根據預設,PowerShell 會將輸出傳送至 PowerShell 主機。 這通常是主控台應用程式。 不過,您可以將輸出重新導向至文本檔,並將錯誤輸出重新導向至一般輸出數據流。

您可以使用下列方法來重新導向輸出:

  • 使用 Out-File Cmdlet,將命令輸出傳送至文字檔。 一般而言,當您需要使用 Out-FileEncodingForceWidth 參數等參數時,請使用 NoClobber Cmdlet。

  • 使用 Tee-Object Cmdlet,它會將命令輸出傳送至文本文件,然後將它傳送至管線。

  • 使用 PowerShell 重定向運算符。 使用重新導向運算符(>)重新導向 PowerShell 命令(Cmdlet、函式、腳本)的輸出,功能上等同於將其管線到沒有額外參數的 Out-File。 PowerShell 7.4 在用來重新導向原生命令 stdout 數據流時,已變更重新導向運算符的行為。

如需資料流的詳細資訊,請參閱 about_Output_Streams

可重新導向的輸出資料流程

PowerShell 支援下列輸出數據流的重新導向。

串流# 描述 引進於 寫入 Cmdlet
1 成功 數據流 PowerShell 2.0 Write-Output
2 錯誤 串流 PowerShell 2.0 Write-Error
3 警告 串流 PowerShell 3.0 Write-Warning
4 詳細資訊 數據流 PowerShell 3.0 Write-Verbose
5 偵錯 數據流 PowerShell 3.0 Write-Debug
6 數據流 資訊 PowerShell 5.0 Write-InformationWrite-Host
* 所有串流 PowerShell 3.0

PowerShell 中也有 Progress 數據流,但不支援重新導向。

重要

成功錯誤 數據流類似於其他 shell 的 stdout 和 stderr 數據流。 不過,stdin 未連線到 PowerShell 管線以進行輸入。

PowerShell 重新導向運算子

PowerShell 重新導向運算符如下所示,其中 n 代表數據流編號。 如果未指定任何數據流,則 成功 數據流 (1) 是預設值。

操作員 描述 語法
> 將指定的數據流傳送至檔案。 n>
>> 指定的數據流附加至檔案。 n>>
>&1 將指定的數據流 重新導向至 成功 數據流。 n>&1

注意

不同於某些 Unix 殼層,您只能將其他資料流重新導向到 Success 資料流。

重新導向原生命令的輸出

PowerShell 7.4 已變更重新導向運算符在重新導向原生命令 stdout 流時的行為。 重新導向運算子現在會在從原生命令重新導向輸出時保留位元組數據流數據。 PowerShell 不會解譯重新導向的數據或新增任何其他格式。 如需詳細資訊,請參閱 範例 #7

範例

範例 1:將錯誤和輸出重新導向至檔案

本範例會在一個成功的項目和一個失敗的項目上執行 dir

dir C:\, fakepath 2>&1 > .\dir.log

它會使用 2>&1錯誤 數據流重新導向至 Success 數據流,> 並將結果 Success 數據流傳送至名為 dir.log 的檔案

範例 2:將所有成功串流數據傳送至檔案

這個範例會將所有 Success 數據流數據傳送至名為 script.log的檔案。

.\script.ps1 > script.log

範例 3:將成功、警告和錯誤數據流傳送至檔案

此範例示範如何結合重新導向運算符來達成所需的結果。

&{
   Write-Warning "hello"
   Write-Error "hello"
   Write-Output "hi"
} 3>&1 2>&1 > C:\Temp\redirection.log
  • 3>&1 會將 警告 數據流重新導向至 成功 數據流。
  • 2>&1 會將 錯誤 數據流重新導向至 成功 數據流(現在也包含所有 警告 數據流數據)
  • > 會將 成功 數據流重新導向至名為 的檔案,其中現在同時包含 警告C:\temp\redirection.log 數據流。

範例 4:將所有數據流重新導向至檔案

這個範例會將名為 script.ps1 腳本的所有數據流輸出傳送至名為 script.log的檔案。

.\script.ps1 *> script.log

範例 5:隱藏所有 Write-Host 和資訊數據流數據

此範例會隱藏所有資訊數據流數據。 如需進一步了解 資訊流指令集,請參閱 Write-HostWrite-Information

&{
   Write-Host "Hello"
   Write-Information "Hello" -InformationAction Continue
} 6> $null

範例 6:顯示動作喜好設定的效果

動作喜好設定變數和參數可以變更寫入特定數據流的內容。 此範例中的腳本示範 $ErrorActionPreference 值如何影響寫入至 Error 數據流的內容。

$ErrorActionPreference = 'Continue'
$ErrorActionPreference > log.txt
Get-Item /not-here 2>&1 >> log.txt

$ErrorActionPreference = 'SilentlyContinue'
$ErrorActionPreference >> log.txt
Get-Item /not-here 2>&1 >> log.txt

$ErrorActionPreference = 'Stop'
$ErrorActionPreference >> log.txt
try {
    Get-Item /not-here 2>&1 >> log.txt
}
catch {
    "`tError caught!" >> log.txt
}
$ErrorActionPreference = 'Ignore'
$ErrorActionPreference >> log.txt
Get-Item /not-here 2>&1 >> log.txt

$ErrorActionPreference = 'Inquire'
$ErrorActionPreference >> log.txt
Get-Item /not-here 2>&1 >> log.txt

$ErrorActionPreference = 'Continue'

當我們執行此腳本時,當 $ErrorActionPreference 設定為 Inquire時,我們會收到提示。

PS C:\temp> .\test.ps1

Confirm
Can't find path 'C:\not-here' because it doesn't exist.
[Y] Yes  [A] Yes to All  [H] Halt Command  [S] Suspend  [?] Help (default is "Y"): H
Get-Item: C:\temp\test.ps1:23
Line |
  23 |  Get-Item /not-here 2>&1 >> log.txt
     |  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | The running command stopped because the user selected the Stop option.

當我們檢查記錄檔時,我們會看到下列內容:

PS C:\temp> Get-Content .\log.txt
Continue

Get-Item: C:\temp\test.ps1:3
Line |
   3 |  Get-Item /not-here 2>&1 >> log.txt
     |  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | Cannot find path 'C:\not-here' because it does not exist.

SilentlyContinue
Stop
    Error caught!
Ignore
Inquire

範例 7:從原生命令重新導向二進位數據

從 PowerShell 7.4 開始,PowerShell 會將原生命令的 stdout 數據流重新導向至檔案,或將位元組數據流數據傳送至原生命令的 stdin 數據流時,會保留位元組數據流數據。

例如,使用原生命令 curl 您可以下載二進位檔,並使用重新導向將它儲存至磁碟。

$uri = 'https://github.com/PowerShell/PowerShell/releases/download/v7.3.7/powershell-7.3.7-linux-arm64.tar.gz'

# native command redirected to a file
curl -s -L $uri > powershell.tar.gz

您也可以使用管線將位元組數據流數據傳送至另一個原生命令的 stdin 資料流。 下列範例會使用 curl下載壓縮的 TAR 檔案。 下載的檔案數據會串流至 tar 命令,以擷取封存的內容。

# native command output piped to a native command
curl -s -L $uri | tar -xzvf - -C .

您也可以使用管道將 PowerShell 命令的位元組流輸出傳送至原生命令的輸入。 下列範例會使用 Invoke-WebRequest 下載與上一個範例相同的 TAR 檔案。

# byte stream piped to a native command
(Invoke-WebRequest $uri).Content | tar -xzvf - -C .

# bytes piped to a native command (all at once as byte[])
,(Invoke-WebRequest $uri).Content | tar -xzvf - -C .

當將 stderr 輸出重新導向至 stdout時,此功能不支援位元組數據流數據。 當您結合 stderrstdout 數據流時,合併的數據流會被視為字串數據。

註釋

未附加數據(>n>)的重新導向運算符會覆寫指定檔案的目前內容,而不會發出警告。

不過,如果檔案是唯讀、隱藏或系統檔案,重新導向 會失敗。 附加重新導向運算子(>>n>>)不會寫入唯讀檔案,但會將內容附加至系統或隱藏的檔案。

若要強制將內容重新導向至唯讀、隱藏或系統檔案,請使用 Out-File Cmdlet 搭配其 Force 參數。

當您寫入檔案時,重新導向運算符會使用 UTF8NoBOM 編碼。 如果檔案有不同的編碼方式,則輸出可能無法正確格式化。 若要以不同的編碼方式寫入檔案,請使用 Out-File Cmdlet 搭配其 Encoding 參數。

寫入檔案時的輸出寬度

當您使用 Out-File 或重新導向運算元寫入檔案時,PowerShell 會根據執行中的主控台寬度,將資料表輸出格式化為檔案。 例如,在主控台寬度設定為80個資料行的系統上,使用類似 Get-ChildItem Env:\Path > path.log 之類的命令將資料表輸出記錄到檔案時,檔案中的輸出會截斷為80個字元:

Name                         Value
----                         -----
Path                         C:\Program Files\PowerShell\7;C:\WINDOWS…

考慮到主控台寬度可能會在執行腳本的系統上任意設定,您可能會偏好將 PowerShell 格式的資料表根據您指定的寬度輸出到檔案。

Out-File Cmdlet 提供 Width 參數,可讓您設定想要用於資料表輸出的寬度。 您不必在叫用 -Width 2000的任何地方新增 Out-File,您可以使用 $PSDefaultParameterValues 變數,針對腳本中 Out-File Cmdlet 的所有使用方式設定此值。 由於重新導向運算元(>>>)實際上是 Out-File的別名,因此設定整個腳本的 Out-File:Width 參數也會影響重新導向運算子的格式寬度。 將下列命令放在文稿頂端附近,以設定整個文稿的 Out-File:Width

$PSDefaultParameterValues['Out-File:Width'] = 2000

當記錄數據表格式化輸出時,增加輸出寬度會增加記憶體耗用量。 如果您要將大量表格式數據記錄到檔案中,並且知道可以適應較小的寬度,那就使用較小的寬度。

在某些情況下,例如 Get-Service 輸出,若要使用額外的寬度,您必須在輸出至檔案之前將輸出通過 Format-Table -AutoSize 管道傳送。

$PSDefaultParameterValues['Out-File:Width'] = 2000
Get-Service | Format-Table -AutoSize > services.log

如需 $PSDefaultParameterValues的詳細資訊,請參閱 about_Preference_Variables

比較運算子的潛在混淆

> 運算符不會與 大於 比較運算元混淆(通常以其他程序設計語言的 > 表示)。

視所比較的物件而定,使用 > 的輸出看起來可能正確(因為 36 不大於 42)。

PS> if (36 > 42) { "true" } else { "false" }
false

不過,檢查本機檔案系統可以看到一個名為 42 的文件已被寫入,內容為 36

PS> dir

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
------          1/02/20  10:10 am              3 42

PS> cat 42
36

嘗試使用反向比較 <(小於),會產生系統錯誤:

PS> if (36 < 42) { "true" } else { "false" }
ParserError:
Line |
   1 |  if (36 < 42) { "true" } else { "false" }
     |         ~
     | The '<' operator is reserved for future use.

如果數值比較是必要作業,則應該使用 -lt-gt。 如需詳細資訊,請參閱 -gt中的 運算符。

另請參閱