Keep colors when piping commands on Linux

tl;dr: --color=always

Colorized text is incredibly useful in the terminal since it makes it easier to quickly navigate a sea of text. Many Linux/GNU commands can output in color, but the color codes can get stripped out when piping to other commands.

I thought that it was the receiving command, such as tail, that was stripping out the color information, but it turns out it's actually the initial command, such as ls or dmesg, that is generating the color information.


--color[=WHEN] colorize the output; WHEN can be 'always' (default if omitted), 'auto', or 'never'; more info below


-L, --color[=when] Colorize the output. The optional argument when can be auto, never or always. If the when argument is omitted, it defaults to auto. The colors can be disabled, for the current built-in default see --help output. See also the COLORS section.

For ls and dmesg, if color is set to "auto" then it will only output color codes if it is sending output to the terminal. Since a pipe is not the terminal it won't send color codes.

So to use more with dmesg and retain color information we'll need to tell dmesg to always output color codes:

$ dmesg --color=always|more

Or to use tail with ls:

$ ls -lt --color=always|tail

Why do terminal commands have this behavior? If we output a command with color codes to a file the results will look like this:

$ ls -lt --color=always > /tmp/lstest

total 8668
-rw-r--r-- 1 root root 182810 Jan 11 2018 ^[[0m^[[01;31mdpkg.status.1.gz^[[0m
-rw-r--r-- 1 root root 1497 Jan 11 2018 ^[[01;31mapt.extended_states.1.gz^[[0m

Sometimes this is undesired behavior, but it can be useful if the command used to later view the results supports color codes such as cat or tail.

On my system by default less doesn't interpret color codes. Instead it displays the color code control characters. To have less render the colors instead use either "-r" or "-R"

$ less -R /tmp/lstest