英文:
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
彩色内容会被渲染为:
在out.txt
文件中,彩色内容以转义码的形式表示:
Write-Host
命令的颜色
这里我使用Write-Host
命令将文本显示为红色:
然而,如果将输出重定向到文件中,我们可以看到这次输出文件中并没有保留颜色信息:
问题
在使用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:
The colors are represented in out.txt
as escape codes:
Write-Host colors
Here I'm using Write-Host
to display text in red:
However, if I redirect output to a file, we can see that this time the colors are not represented in the resulting file:
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-Host
将InformationRecord对象写入信息流。如果你使用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
甚至可以这样:
Set-MarkdownOption -ItalicsForegroundColor '[91m'
('Make this *red* text' | ConvertFrom-MarkDown -AsVT100EncodedString).VT100EncodedString > .\out.txt
Get-Content .\out.txt
英文:
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
Or even:
Set-MarkdownOption -ItalicsForegroundColor '[91m'
('Make this *red* text' | ConvertFrom-MarkDown -AsVT100EncodedString).VT100EncodedString > .\out.txt
Get-Content .\out.txt
答案2
得分: 2
这是使用bsdutils中的script
命令的一种方法:
这是基于以下答案的:
使用案例
另外,通过将这种方法与terminal-to-html
结合使用:
我能够将任意颜色的PowerShell输出渲染为HTML。
这是一个屏幕截图,它将此PowerShell脚本的输出渲染为HTML:
英文:
Here's one approach using the script
command from bsdutils:
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:
答案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
...
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论