将 PowerShell 输出的彩色内容重定向到文件中。

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

PowerShell output with color redirected to file

问题

dir命令输出的彩色内容保存到文件中

如果我在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-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

将 PowerShell 输出的彩色内容重定向到文件中。

甚至可以这样:

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

将 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.html
匿名

发表评论

匿名网友

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

确定