phd's helpful answer提供了最佳的解决方案。
至于为什么... | Out-Null
无效:
Out-Null
仅抑制来自外部程序(例如git
)的stdout输出,而不是stderr输出。
git
和许多CLI(控制台/终端程序)一样,使用stderr流不仅报告错误,还用于状态信息 - 基本上是任何非数据内容。
要抑制stdout和stderr输出,请使用*> $null
:
git clean -fd *> $null
*> $null
抑制了所有输出流;而外部程序只有2个(stdout和stderr),将*>$null
应用于PowerShell本机命令会使所有6个输出流静音。
有关更多信息,请参见关于重定向。
根据nmbell的反馈,可以进行以下改进:
>$null
(或1>$null
)可用于有选择性地抑制stdout输出,这与| Out-Null
的效果相同。
2>$null
可用于有选择性地抑制stderr输出。
如上所述,*>$null
会使所有流静音。
当然,除了使用$null
来抑制输出外,重定向目标也可以是文件(名称或路径)。
注意:
PowerShell在其管道中逐行处理外部程序的输出。如果输出被捕获到一个变量中($out = ...
)并且包含2行或更多行,则存储为行(字符串)的数组([object[]]
)。
PowerShell只与外部程序使用文本(字符串)进行通信,无论是发送还是接收数据,这意味着可能会涉及字符编码问题。
有关这两个方面的更多信息,请参见this answer。
带有示例的场景:
设置:
# Construct a platform-appropriate command, stored in a script block ({ ... })
# that calls an external program (the platform-native shell) that outputs
# 1 line of stdout and 1 line of stderr output each, and can later be
# invoked with `&`, the call operator.
$externalCmd = if ($env:OS -eq 'Windows_NT') { # Windows
{ cmd /c 'echo out & echo err >&2' }
} else { # Unix (macOS, Linux)
{ sh -c 'echo out; echo err >&2' }
}
捕获标准输出,通过stderr传递:
PS> $captured = & $externalCmd; "Captured: $captured"
err # Stderr output was *passed through*
Captured: out # Captured stdout output.
使用2>$null
捕获标准输出,禁止错误输出:
PS> $captured = & $externalCmd 2>$null; "Captured: $captured"
Captured: out # Captured stdout output - stderr output was suppressed.
使用*>&1
同时捕获stdout和stderr:
PS> $captured = & $externalCmd *>&1 | % ToString; "Captured: $captured"
Captured: out err # *Combined* stdout and stderr output.
注意:
% ToString
是 ForEach-Object ToString
的简写形式,它在每个输出对象上调用 .ToString()
方法,确保 PowerShell 封装的 System.Management.Automation.ErrorRecord
实例中的 stderr 行被转换回 字符串。$captured
接收一个由两个元素组成的 数组 ([object[]]
) - 分别包含 stdout 和 stderr 行;在本例中,它是 PowerShell 的字符串插值 将它们转换为单行、以空格分隔的字符串。仅捕获标准错误流,抑制标准输出流:
PS> $captured =
& $externalCmd *>&1 |
? { $_ -is [System.Management.Automation.ErrorRecord] } |
% ToString; "Captured: $captured"
Captured: err # Captured stderr output *only*.
注意:
? { $_ -is [System.Management.Automation.ErrorRecord] }
是 Where-Object { $_ -is [System.Management.Automation.ErrorRecord] }
的缩写形式,它只传递标准错误行(通过测试包装类型)并再次使用% ToString
将其转换回字符串。
这种技术既不明显也不方便; GitHub suggestion #4332 提出了一种语法,例如2> variable:stderr
以支持将流重定向到变量,例如在本例中的$stderr
。