介绍如何将 PowerShell 的输出重定向到文本文件。

默认情况下,PowerShell 会将输出发送到 PowerShell 主机。 通常是控制台应用程序。 但是,可以将输出重定向到文本文件,并且可以将错误输出重定向到常规输出流。

可以使用以下方法来重定向输出:

  • 使用 Out-File cmdlet,它会将命令输出发送到文本文件。 通常,需要使用其参数(例如 Encoding Force Width NoClobber 参数)时,可以使用 Out-File cmdlet。

  • 使用 Tee-Object cmdlet,它会将命令输出发送到文本文件,然后将其发送到管道。

  • 使用 PowerShell 重定向运算符。 使用重定向运算符 > (cmdlet、函数、脚本)将 PowerShell 命令的输出重定向在功能上等同于管道到 Out-File 没有额外参数。 PowerShell 7.4 在用于重定向本机命令的 stdout 流时更改了 重定向运算符的行为。

    有关流的详细信息,请参阅 about_Output_Streams

    可重定向输出流

    PowerShell 支持重定向以下输出流。

    已引入的版本 写入 Cmdlet

    Success Error 流类似于其他 shell 的 stdout 和 stderr 流。 但是,stdin 未连接到用于输入的 PowerShell 管道。

    PowerShell 重定向运算符

    PowerShell 重定向运算符如下所示,其中 n 表示流编号。 如果未指定流,则默认为 Success 流 ( 1 )。

    Description

    从本机命令重定向输出

    PowerShell 7.4 在用于重定向本机命令的 stdout 流时更改了 重定向运算符的行为。 重定向运算符现在在从本机命令重定向输出时保留字节流数据。 PowerShell 不会解释重定向的数据或添加任何其他格式。 有关详细信息,请参阅 示例 #7

    示例 1:将错误重定向并输出到文件

    此示例对成功项和失败项运行 dir

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

    它使用 2>&1Error 流重定向到 Success 流,并使用 > 将生成的 Success 流发送到名为 dir.log 的文件

    示例 2:将所有 Success 流数据发送到文件

    此示例将所有 Success 流数据发送到名为 script.log 的文件。

    .\script.ps1 > script.log
    

    示例 3:将 Success、Warning 和 Error 流发送到文件

    此示例演示如何合并重定向运算符以实现所需的结果。

    Write-Warning "hello" Write-Error "hello" Write-Output "hi" } 3>&1 2>&1 > C:\Temp\redirection.log
  • 3>&1Warning 流重定向到 Success 流。
  • 2>&1Error 流重定向到 Success 流(现在还包括所有 Warning 流数据)
  • > 可将 Success 流(现在包含 WarningError 流)重定向到名为 C:\temp\redirection.log 的文件。
  • 示例 4:将所有流重定向到文件

    此示例将所有流输出从名为 script.ps1 的脚本发送到名为 script.log 的文件。

    .\script.ps1 *> script.log
    

    示例 5:禁止所有 Write-Host 和 Information 流数据

    此示例禁止显示所有信息流数据。 要了解有关 Information 流 cmdlet 的详细信息,请参阅 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
        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 时,此功能不支持字节流数据。 合并 stderr 流和 stdout 流时,会将合并后的流视为字符串数据。

    不追加数据的重定向运算符(>n>)会覆盖指定文件的当前内容,而不会发出警告。

    但是,如果文件是只读文件、隐藏文件或系统文件,则重定向会失败。 追加重定向运算符(>>n>>)不会写入只读文件,但会将内容追加到系统或隐藏文件。

    若要强制将内容重定向到只读、隐藏或系统文件,请使用带有 Force 参数的 Out-File cmdlet。

    写入文件时,重定向运算符将使用 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 参数,允许你设置表格输出所需的宽度。 不必在调用 Out-File 的任何地方添加 -Width 2000,而是可以使用 $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
    

    尝试使用反向比较 <(小于)会产生系统错误:

    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。 有关详细信息,请参阅 about_Comparison_Operators 中的 -gt 运算符。

  • about_Command_Syntax
  • about_Operators
  • about_Output_Streams
  • about_Path_Syntax
  • Out-File
  • Tee-Object
  • Write-Debug
  • Write-Error
  • Write-Host
  • Write-Information
  • Write-Output
  • Write-Progress
  • Write-Verbose
  • Write-Warning
  • 即将推出:在整个 2024 年,我们将逐步取消以“GitHub 问题”作为内容的反馈机制,并将其替换为新的反馈系统。 有关详细信息,请参阅:https://aka.ms/ContentUserFeedback

    提交和查看相关反馈

  •