In PowerShell, is there a way to preserve the ANSI control codes used to convey color information to the console when assigning a program's output to a variable?
For instance, I use Test Kitchen which provides colored output unique to each suite of tests to run. When I run kitchen create INSTANCE
, I get output in several colors. However, if I assign the output to a variable, or pipe it to another cmdlet such as Tee-Object
, that color information is lost. It seems that PowerShell strips this information out when the result is sent down the pipeline or assigned to a variable:
kitchen create INSTANCE # Colored output
$output = kitchen create INSTANCE
Write-Host $output # Color information is lost
Curiously though, I can implement control codes in my own strings and PowerShell is able to honor them when Virtual Terminal is enabled. These survive variable assignment, unlike command output:
$output = "`u{001b}[31mHello"
Write-Host $output # Results in colored output
So it seems that the color information is being stripped out only from a program's output, and only if the value is assigned or sent down the pipeline. Is there a way to preserve these control codes from external commands?
To add to your own answer:
On Windows I'm not aware of any simple solutions, though perhaps there is a programmatic way to do what the script
utility does on Unix-like platforms (see next point).
On Unix-like platforms, you can use the script
utility to make external programs believe they are connected to a terminal and thus make them produce colored output they would otherwise suppress:
script
is not a POSIX-mandated utility, but it ships with at least some Linux distros, notably Ubuntu, as well as with macOS.Example:
Note:
ls --color=auto
is used as a readily available test command, because it exhibits the conditional coloring behavior.
ls --color=always
would exhibit unconditional coloring behavior, and would therefore obviate the need for script
- as such, ls
is an example of a utility that does allow you to request unconditional coloring; ls --color=auto
merely serves as a stand-in for utilities that do not.
The variable assignment below ($out = ...
) is enclosed in (...)
in order to pass the value being assigned through, so you'll see right away that the coloring is preserved.
Linux
($out = script -qc 'ls --color=auto' /dev/null)
($out = script -q /dev/null ls --color=auto)