英文:
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
颜色将会被呈现:
颜色在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-Host
的Write-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
英文:
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
命令的一种方法:
这是基于以下答案的:
> 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
英文:
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
...
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论