ls -l --color=auto | tee output.log

Without pipe/tee it's colored. How can I make it so that it stays colored while using tee (can be colored only on the screen, I don't care about colors in logs).


5 Answers 5


Simply insert unbuffer before any command to make it think it is writing to an interactive output even if it is actually piping into another executable. This will preserve color in the case of ls.

For example

unbuffer ls -l --color=auto | tee output.log

If you don't already have it installed, on Ubuntu and other Debian-ish Linux distributions you can install unbuffer by doing.

sudo apt-get install expect-dev
  • 9
    Another solution, which does not require installing anything, is at stackoverflow.com/questions/3515208/…
    – Tgr
    Jan 31, 2015 at 2:51
  • 5
    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? Jul 10, 2015 at 18:48
  • 3
    Ugh, that makes password entries show your password in cleartext!
    – AndiDog
    Aug 20, 2015 at 13:37
  • 1
    @Tgr That solution didn't work for me on OS X trying to get the raw colored output of xcodebuild— instead I got chopped-up lines with no color. unbuffer xcodebuild | less -R worked flawlessly, however. Nov 24, 2015 at 5:33
  • 5
    You don't need the expect-dev package. expect is enough.
    – Yajo
    Sep 4, 2018 at 9:53

Use the ls option --color=always

--color=auto will not color output to a pipeline - for obvious reasons.

The main page says the following:

With --color=auto, color codes are output only if standard output is connected to a terminal (tty).

  • 2
    OK. That explains it. But can I still somehow see the colors on the screen? (It's a TTY after all). I don't mind NOT having them in the logfile, but I surely want them on my screen. Nov 2, 2011 at 10:46
  • I think I made myself not clear enough. ls -l was just an example. I have a completely different command (heroku logs) that strips colors when piped to tee. And I want to "fix/change" tee/pipe, not the command I'm executing. Nov 2, 2011 at 12:00
  • 1
    @Pawel, you can't easily fix it in tee/pipe as tee/pipe are not stripping these color codes. The problem is that the initial command sees it is not writing to the terminal. You need a pseudo-terminal that acts like a pipe but which commands see as a terminal. Nov 2, 2011 at 16:10
  • 4
    @PawełGościcki this answer only fixes the problem for ls. See my answer that fixes the problem for all programs, including heroku logs. Jun 16, 2014 at 3:25
  • 1
    grep also has this option
    – Jack Wasey
    Aug 7, 2017 at 19:28

I'll expand the script solution given in the comment of the accepted answer. Using script may be useful in case you can't or don't want to install the expect package that contains the unbuffer command.

Print ls output to stdout and file with color codes:

script -efq output.log -c "ls -l --color=auto"

where (man script):

  -e, --return
         Return the exit code of the child process.  Uses the same
         format as bash termination on signal termination exit code is 128+n.
  -f, --flush
         Flush output after each write.  This is nice for telecooperation:
        one person does `mkfifo foo; script -f foo', and another can 
        supervise real-time what is being done using `cat foo'.
  -q, --quiet
         Be quiet (do not write start and done messages to either 
         standard output or the typescript file).

View the output file with colors:

less -r output.log
  • 2
    -e is the same as --return - no need for both; -efq is --return --flush --quiet. May 13, 2019 at 13:37
  • @NoelMaersk Thanks. I incorporated the parameter explanations in the answer. May 14, 2019 at 4:11
  • Perfect alternative for unbuffer thank you!
    – Mark
    Jun 12, 2020 at 23:44
  • Clean! I turned it into a function with usage output file command. SO doesn't support this much code in a comment so I put it here. Apr 13, 2021 at 1:08
  • Look my answer for a more general approach. The script just forward the input to stdout instead of a file. Then it can be used for piping to a command directly
    – nadapez
    May 10 at 0:35

Here is a function based off this clean answer that I couldn't fit in the comments.

    script -efq $output_file -c "$command"
    less $output_file


output file command

script -efq -c "ls --color=auto" >(cat) | tee output.log

For convenience I created this script:

script -efq -c "$*" >(cat)

call it say unbuff and then

unbuff ls --color=auto | tee output.log

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.