简短说明
介绍如何将 PowerShell 的输出重定向到文本文件。
详细说明
默认情况下,PowerShell 会将输出发送到 PowerShell 主机。 通常是控制台应用程序。 但是,可以将输出重定向到文本文件,并且可以将错误输出重定向到常规输出流。
可以使用以下方法来重定向输出:
使用
Out-Filecmdlet,该 cmdlet 将命令输出发送到文本文件。 通常,如果需要使用Out-File、Encoding、Force或Width参数等参数,请使用NoClobbercmdlet。使用
Tee-Objectcmdlet,该 cmdlet 将命令输出发送到文本文件,然后将其发送到管道。使用 PowerShell 重定向运算符。 使用重定向运算符(
>)重定向 PowerShell 命令(cmdlet、函数、脚本)的输出,在功能上等效于通过没有额外参数的管道传送到Out-File。 PowerShell 7.4 在用于重定向本机命令的 stdout 流时更改了重定向运算符的行为。
有关流的详细信息,请参阅 about_Output_Streams。
可重定向输出流
PowerShell 支持重定向以下输出流。
| 流编号 | 描述 | 已引入的版本 | 写入 Cmdlet |
|---|---|---|---|
| 1 | Success 流 | PowerShell 2.0 | Write-Output |
| 2 | Error 流 | PowerShell 2.0 | Write-Error |
| 3 | 警告 数据流 | PowerShell 3.0 | Write-Warning |
| 4 | Verbose 流 | PowerShell 3.0 | Write-Verbose |
| 5 | Debug 流 | PowerShell 3.0 | Write-Debug |
| 6 | 信息流 | PowerShell 5.0 |
Write-Information,Write-Host |
| * | 所有流 | PowerShell 3.0 |
PowerShell 中还存在 Progress 流,但它不支持重定向。
重要
“成功”流和“错误”流类似于其他 shell 的 stdout 和 stderr 流。 但是,stdin 并未与 PowerShell 管道相连接以进行输入。
PowerShell 重定向运算符
PowerShell 重定向运算符如下所示,其中 n 表示流号。 如果未指定流,则 成功 流(1)是默认值。
| 操作员 | 描述 | 语法 |
|---|---|---|
> |
将指定的流发送到文件。 | n> |
>> |
将 指定的流追加到文件。 | n>> |
>&1 |
将指定流 重定向到 Success 流。 | n>&1 |
注意
与某些 Unix shell 不同,只能将其他流重定向到 Success 流。
从本机命令重定向输出
PowerShell 7.4 在用于重定向本机命令的 stdout 流时更改了重定向运算符的行为。 重定向运算符现在在从本地命令重定向输出时保留字节流数据。 PowerShell 不会解释重定向的数据或添加任何其他格式。 有关详细信息,请参阅 示例 #7。
例子
示例 1:将错误和输出重定向到文件
此示例对一个成功项和一个失败项运行 dir。
dir C:\, fakepath 2>&1 > .\dir.log
它使用 2>&1 将 错误 流重定向到 Success 流,> 将生成的 Success 流发送到名为 dir.log 的文件
示例 2:将所有成功流数据发送到文件
此示例将所有 成功 流数据发送到名为 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将 警告 流重定向到 Success 流。 -
2>&1将 错误 流重定向到 成功 流(现在还包括所有 警告 流数据) -
>将 成功 流(现在包含 警告 和 错误 流)重定向到名为C:\temp\redirection.log的文件。
示例 4:将所有流重定向到文件
此示例将所有流输出从名为 script.ps1 的脚本发送到名为 script.log的文件。
.\script.ps1 *> script.log
示例 5:禁止显示所有 Write-Host 和信息流数据
此示例禁止显示所有信息流数据。 要了解有关 Information 流 cmdlet 的详细信息,请参阅 Write-Host 和 Write-Information
&{
Write-Host "Hello"
Write-Information "Hello" -InformationAction Continue
} 6> $null
示例 6:显示操作首选项的效果
操作首选项变量和参数可以更改写入到特定流的内容。 此示例中的脚本演示如何 $ErrorActionPreference 值影响写入 错误 流的内容。
$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 开始,将本机命令的 stdout 流重定向到文件时,或者将字节流数据流传输到本机命令的 stdin 流时,PowerShell 会保留字节流数据。
例如,使用本机命令 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时,此功能不支持字节流数据。 合并 stderr 和 stdout 流时,合并的流将被视为字符串数据。
注释
不追加数据的重定向运算符(> 和 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中的 运算符。