Can colorized output be captured via shell redirect? [duplicate]
Asked Answered
R

7

114

Various bash commands I use -- fancy diffs, build scripts, etc, produce lots of color output.

When I redirect this output to a file, and then cat or less the file later, the colorization is gone -- presumably b/c the act of redirecting the output stripped out the color codes that tell the terminal to change colors.

Is there a way to capture colorized output, including the colorization?

Raynata answered 18/8, 2010 at 18:11 Comment(1)
lol @ the dupe notice: "How to trick an application into thinking its stdout is a terminal, not a pipe" really seems to the same question as "Can colorized output be captured via shell redirect?"Brewhouse
P
78

One way to capture colorized output is with the script command. Running script will start a bash session where all of the raw output is captured to a file (named typescript by default).

Puck answered 18/8, 2010 at 18:19 Comment(9)
An example: script -q /dev/null ls | catDisloyal
This causes the resulting file to contain color codes (of course); is there any way to then print the file in a way that makes use of the color codes and properly displays the colors in the terminal? I tried echo -e $(< filename), but that doesn't seem to work.Amon
....actually, echo -e $(< filename ) does seem to colorize output, but for some reason the first part of the output seems to be obscured by Script done on <DATE>.Amon
There's a script called ansi2html that does an OK job of converting the resulting typescript to HTML.Wodge
another example: script<enter for new shell> lolcat /etc/motd > /tmp/color_motd Then edit the typescript file and strip out the start and end output as needed.Kenton
script does not work piping to interactive commands like less, unless you add more complicated redirects. It's easier to use unbuffer stackoverflow.com/a/1410273Confectioner
If you need to it can be then made into a pdf with https://mcmap.net/q/189928/-how-to-print-out-pdf-file-with-script-generated-highlighted-outputCrossbench
less -R will let you view colors.Jenniejennifer
The script command is unavailable in Git Bash for WindowsPolymer
T
51

Redirecting doesn't strip colors, but many commands will detect when they are sending output to a terminal, and will not produce colors by default if not. For example, on Linux ls --color=auto (which is aliased to plain ls in a lot of places) will not produce color codes if outputting to a pipe or file, but ls --color will. Many other tools have similar override flags to get them to save colorized output to a file, but it's all specific to the individual tool.

Even once you have the color codes in a file, to see them you need to use a tool that leaves them intact. less has a -r flag to show file data in "raw" mode; this displays color codes. edit: Slightly newer versions also have a -R flag which is specifically aware of color codes and displays them properly, with better support for things like line wrapping/trimming than raw mode because less can tell which things are control codes and which are actually characters going to the screen.

Trella answered 18/8, 2010 at 18:30 Comment(2)
ls --color is the same as ls --color=always - you're thinking of ls --color=autoIncompliant
⁺¹, you just solved our discuss about whether it is the application determines was it redirected to file, or is it the shell itself when does redirect takes care of stripping the color ANSI symbols.Deni
K
40

Inspired by the other answers, I started using script. I had to use -c to get it working though. All other answers, including tee, different script examples did not work for me.

Context:

  • Ubuntu 16.04
  • running behavior tests with behave and starting shell command during the test with python's subprocess.check_call()

Solution:

script --flush --quiet --return /tmp/ansible-output.txt --command "my-ansible-command"

Explanation for the switches:

  • --flush was needed, because otherwise the output is not well live-observable, coming in big chunks
  • --quiet supresses the own output of the script tool
  • -c, --command directly provides the command to execute, piping from my command to script did not work for me (no colors)
  • --return to make script propagate the exit code of my command so I know if my command has failed
Kenrick answered 6/3, 2017 at 9:19 Comment(3)
Best answer! Thanks.Tapley
I love that it even works with arguments. To suppress terminal output while still writing to the file, add > /dev/null to the end of the command (script --flush --quiet --return /tmp/ansible-output.txt --command "my-ansible-command" > /dev/null).Relive
Add -a flag to append to log file.Ceasar
R
19

I found that using script to preserve colors when piping to less doesn't really work (less is all messed up and on exit, bash is all messed up) because less is interactive. script seems to really mess up input coming from stdin even after exiting.

So instead of running:

script -q /dev/null cargo build | less -R

I redirect /dev/null to it before piping to less:

script -q /dev/null cargo build < /dev/null | less -R

So now script doesn't mess with stdin and gets me exactly what I want. It's the equivalent of command | less but it preserves colors while also continuing to read new content appended to the file (other methods I tried wouldn't do that).

Roderica answered 13/2, 2016 at 4:55 Comment(6)
By the way, script doesn't exit as long as the pipeline is running. So in your first command above (actually both of them), it doesn't exit until less does.Lucrative
This is great. A major use case for me is reading colored grep output that's taller than the height of my screen, which doesn't really make sense except with a reader like less that can let me scroll coherently.Dorsum
any idea on how to get this to work with shell functions? it doesn't seem to work with them. I get command not found or nothing.Spiffing
@Spiffing No because script is an executable so it doesn’t have access to your shell functions. You need to wrap them in standalone scripts.Predispose
It's easier to use unbuffer, which works when piping to less and other interactive commands: stackoverflow.com/a/1410273Confectioner
The command works like a charm script -q --return /dev/null < /dev/null | ls -alhAuburn
L
12

some programs remove colorization when they realize the output is not a TTY (i.e. when you redirect them into another program). You can tell some of those to use color forcefully, and tell the pager to turn on colorization, for example use less -R

Lesbian answered 18/8, 2010 at 18:30 Comment(0)
X
6

This question over on superuser helped me when my other answer (involving tee) didn't work. It involves using unbuffer to make the command think it's running from a shell.

I installed it using sudo apt install expect tcl rather than sudo apt-get install expect-dev.

I needed to use this method when redirecting the output of apt, ironically.

Xuthus answered 5/4, 2017 at 12:30 Comment(0)
X
-4

I use tee: pipe the command's output to teefilename and it'll keep the colour. And if you don't want to see the output on the screen (which is what tee is for: showing and redirecting output at the same time) then just send the output of tee to /dev/null:

command| teefilename> /dev/null

Xuthus answered 28/6, 2016 at 9:5 Comment(5)
What is the version of tee you are using for that? tee 8.21 (shipped with Ubuntu 14.04) does not seem to colorize output by default (tested with cmake + make in a dummy program).Easily
I've just tested it on two machines, one with tee 8.21 and one with tee 8.25. Both worked. I did echo "^[[32mhello^[[0m" | tee temp.txt > /dev/null (where ^[ is the escape character) and then checked temp.txt using cat and using od -c.Xuthus
How do you expect this to work? A program can only tell that it's emitting content to a FIFO -- it can't tell if that FIFO has tee or any other specific program behind it. Thus, if that program is configured to emit color only direct to a TTY, a pipeline to tee will disrupt it as much as a pipeline to any other program.Jone
This isn't a theoretical answer: I have used it successfully! I don't know how it works, but it does for me where a simple redirect fails.Xuthus
this definitively does not work for the purpose of the question. This works only when directly echoing the colors as said in the comments above as that does not check if the terminal is color capable but just echoes whatever is asked to. tee does change the terminal and affects programs which check it the terminal is interactive the same way as a simple direct does.Popp

© 2022 - 2024 — McMap. All rights reserved.