PowerShell 输出的颜色被重定向到文件。

huangapple go评论154阅读模式
英文:

PowerShell output with color redirected to file

问题

dir color output to file

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

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

然后查看输出:

dharmatech@dharmatech-01:/tmp$ cat out.txt

颜色将会被呈现:

PowerShell 输出的颜色被重定向到文件。

颜色在out.txt中以转义码的形式表示:

PowerShell 输出的颜色被重定向到文件。

Write-Host 颜色

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

PowerShell 输出的颜色被重定向到文件。

然而,如果我将输出重定向到文件,我们会看到在结果文件中颜色不会被表示:

PowerShell 输出的颜色被重定向到文件。

问题

Write-Host的情况下,是否有办法让颜色在文件中像dir命令那样呈现?

英文:

dir color output to file

If I run the following command on Ubuntu:

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

and then cat the output:

dharmatech@dharmatech-01:/tmp$ cat out.txt

the colors are rendered:

PowerShell 输出的颜色被重定向到文件。

The colors are represented in out.txt as escape codes:

PowerShell 输出的颜色被重定向到文件。

Write-Host colors

Here I'm using Write-Host to display text in red:

PowerShell 输出的颜色被重定向到文件。

However, if I redirect output to a file, we can see that this time the colors are not represented in the resulting file:

PowerShell 输出的颜色被重定向到文件。

Question

Is there a way to get the colors in the file in the Write-Host case as they are with the dir command?

答案1

得分: 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-HostWrite-Ansi代理命令,但使用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

甚至:

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

PowerShell 输出的颜色被重定向到文件。

PowerShell 输出的颜色被重定向到文件。

英文:

Starting in Windows PowerShell 5.0, Write-Host writes InformationRecord objects to the information stream. This will show if you redirect the information stream to the success stream using 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;}

This object holds the color information in the MessageData property and doesn't include any ANSI control codes by itself:

$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;}

In other words, I don't think that there is any way to preserve the ANSI control code fromWrite-Host. See also: Is there a way to preserve ANSI control codes in PowerShell command output?

You might consider to write your own Write-Ansi proxy command based on Write-Host but there is a general disadvantage with using the Write-Host command as you can only use a single color for the whole output which requires to make use of the -NoNewLne switch and take that in consideration for any proxy command.

Alternatives

Instead of a using a limited (not redirectable) command like:

Write-Host 'This whole line is red.' -ForegroundColor Red

You might consider using the $PSStyle object:

 "This is $($PSStyle.Foreground.Red)red$($PSStyle.Reset) text" #  > .\out.txt

Or, using MarkDown:

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

PowerShell 输出的颜色被重定向到文件。

Or even:

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

PowerShell 输出的颜色被重定向到文件。

答案2

得分: 2

这是使用bsdutils中的script命令的一种方法:

PowerShell 输出的颜色被重定向到文件。

这是基于以下答案的:

> https://stackoverflow.com/a/27399198/268581

用例

另外,通过将这种方法与terminal-to-html结合使用:

> https://github.com/buildkite/terminal-to-html

我能够将任意颜色的PowerShell输出渲染为HTML。

这是一个屏幕截图,它将来自此PowerShell脚本的输出呈现为HTML:

> https://github.com/dharmatech/net-liquidity.ps1

PowerShell 输出的颜色被重定向到文件。

英文:

Here's one approach using the script command from bsdutils:

PowerShell 输出的颜色被重定向到文件。

This is based on this answer:

> https://stackoverflow.com/a/27399198/268581

Use case

As an aside, by combining this approach with terminal-to-html:

> https://github.com/buildkite/terminal-to-html

I'm able to render arbitrary colored PowerShell output as HTML.

Here's a screenshot which renders output from this PowerShell script as HTML:

> https://github.com/dharmatech/net-liquidity.ps1

PowerShell 输出的颜色被重定向到文件。

答案3

得分: 2

这应该是可能的,因为 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 # 输出带有颜色的内容

使用 vi 等工具检查文件时,会显示 Ansi 颜色代码:

...
^[[32;1mUnixMode   User     Group     LastWriteTime    Size   Name^[[0m
^[[32;1m--------   -        -----     -------------    ----   ----^[[0m
...
英文:

This should be possible since Powershell 7.2, as it has support for ANSI colors. Credit for this goes to an earlier answer.

As for an example (Powershell 7.3.3. / MacOS, YMMV):

$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

Examining the file with, say, vi displays the Ansi color codes:

...
^[[32;1mUnixMode   User     Group     LastWriteTime    Size   Name^[[0m
^[[32;1m--------   -        -----     -------------    ----   ----^[[0m
...

huangapple
  • 本文由 发表于 2023年8月9日 12:07:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/76864508-2.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定