将 PowerShell 的输出颜色重定向到文件中

3

dir命令将彩色输出保存到文件

如果我在Ubuntu上运行以下命令:

dharmatech@dharmatech-01:/tmp$ pwsh -Command 'dir' > out.txt

然后将输出连接起来:
dharmatech@dharmatech-01:/tmp$ cat out.txt

颜色呈现如下:

enter image description here

颜色在out.txt中以转义码表示。

enter image description here

写入主机颜色

这里我使用 Write-Host 来以红色显示文本:

enter image description here

然而,如果我将输出重定向到文件,我们可以看到这次颜色没有在生成的文件中表示。

enter image description here

问题
有没有办法在使用Write-Host命令时,以与dir命令相同的方式获取文件中的颜色?
3个回答

3

1
这是你的答案吗,还是你还在寻找中? - Pieterjan
1
@Pieterjan 这只适用于script可用的情况下。所以如果有更便携的方法,我会很感兴趣! - dharmatech

3

自 Powershell 7.2 开始应该是可能的,因为它支持 ANSI 颜色。感谢先前的答案

至于一个例子(Powershell 7.3.3 / MacOS,具体情况可能会有所不同):

$PsStyle.OutputRending = "Ansi"
$s = Get-ChildItem | Select -First 3 | Out-String
Set-Content -path foo.txt $s
Get-Content ./foo.txt # prints out colored output

使用例如vi这样的工具来检查文件,会显示出 Ansi 颜色代码。
...
^[[32;1mUnixMode   User     Group     LastWriteTime    Size   Name^[[0m
^[[32;1m--------   -        -----     -------------    ----   ----^[[0m
...

嘿 @vonPryz ‍♂️ 你能用 Write-Host 'abc' -ForegroundColor Red 让它工作吗? - dharmatech
@dharmatech 你是什么意思?是说Write-Host会显示ANSI控制码吗?还是说Write-Host写的内容也应该带有颜色并保存到文件中? - vonPryz
在你的示例中,你正在使用Get-ChildItem。你能否使用上面展示的Write-Host使你的示例运行起来? - dharmatech
当我尝试使用Write-Host而不是Get-ChildItem来采用你的方法时,红色并没有显示出来。 - dharmatech
请看我在问题中发布的示例案例,它使用红色文本:Write-Host abc -ForegroundColor red。当我使用您的方法处理这个示例时,转义字符似乎没有显示出来。 - dharmatech

3
从 Windows PowerShell 5.0 开始,Write-HostInformationRecord 对象写入 信息流。如果使用 6>&1 将信息流重定向到成功流,则会显示该信息。
$InformationRecord = Write-Host abc -ForegroundColor Red 6>&1
$InformationRecord | Get-Member

   TypeName: System.Management.Automation.InformationRecord

Name            MemberType Definition
----            ---------- ----------
Equals          Method     bool Equals(System.Object obj)
GetHashCode     Method     int GetHashCode()
GetType         Method     type GetType()
ToString        Method     string ToString()
Computer        Property   string Computer {get;set;}
ManagedThreadId Property   uint ManagedThreadId {get;set;}
MessageData     Property   System.Object MessageData {get;}
NativeThreadId  Property   uint NativeThreadId {get;set;}
ProcessId       Property   uint ProcessId {get;set;}
Source          Property   string Source {get;set;}
Tags            Property   System.Collections.Generic.List[string] Tags {get;}
TimeGenerated   Property   datetime TimeGenerated {get;set;}
User            Property   string User {get;set;}

这个对象在MessageData属性中保存颜色信息,本身不包含任何ANSI控制码。
$InformationRecord.MessageData | Get-Member

   TypeName: System.Management.Automation.HostInformationMessage

Name            MemberType Definition
----            ---------- ----------
Equals          Method     bool Equals(System.Object obj)
GetHashCode     Method     int GetHashCode()
GetType         Method     type GetType()
ToString        Method     string ToString()
BackgroundColor Property   System.Nullable[System.ConsoleColor] BackgroundColor {get;set;}
ForegroundColor Property   System.Nullable[System.ConsoleColor] ForegroundColor {get;set;}
Message         Property   string Message {get;set;}
NoNewLine       Property   System.Nullable[bool] NoNewLine {get;set;}

换句话说,我认为没有办法保留来自Write-Host的ANSI控制代码。参见:在PowerShell命令输出中是否有保留ANSI控制代码的方法? 你可以考虑编写自己的Write-Ansi代理命令,基于Write-Host,但使用Write-Host命令存在一个普遍的缺点,即只能为整个输出使用单一颜色,这需要使用-NoNewLine开关,并在任何代理命令中考虑到这一点。
替代方案
不要使用像下面这样受限(无法重定向)的命令:
Write-Host 'This whole line is red.' -ForegroundColor Red

你可以考虑使用 $PSStyle 对象:
 "This is $($PSStyle.Foreground.Red)red$($PSStyle.Reset) text" #  > .\out.txt

或者,使用MarkDown
'Make this *blue* text' > .\out.txt
(Get-Content .\out.txt | ConvertFrom-MarkDown -AsVT100EncodedString).VT100EncodedString

enter image description here

甚至可以是:
Set-MarkdownOption -ItalicsForegroundColor '[91m'
('Make this *red* text' | ConvertFrom-MarkDown -AsVT100EncodedString).VT100EncodedString > .\out.txt
Get-Content .\out.txt

enter image description here


1
我甚至不知道有 ConvertFrom-MarkDown 这个命令。我之前主要使用的是 PowerShell 5.1 版本,现在开始使用 7.3 版本。谢谢你,iRon! - dharmatech

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接