186

Some commands that I use display colors, but when I use them with watch the colors disappears:

watch -n 1 node file.js

Is it possible to have the colors back on somehow?

never_had_a_name
  • 90,630
  • 105
  • 267
  • 383
  • possible duplicate of [How can I make the watch command interpret vt100 sequences?](http://stackoverflow.com/questions/2417824/how-can-i-make-the-watch-command-interpret-vt100-sequences) – l0b0 Apr 11 '12 at 11:29

8 Answers8

228

Some newer versions of watch now support color.

For example watch --color ls -ahl --color.

Related.

If you're seeing monochrome output when you expect color, it's likely that the command you're running within watch is detecting that it's not attached to the terminal and you'll need to force color output. Some examples:

CLICOLOR_FORCE=1 watch --color ls -ahl    # MacOS
watch --color ls -ahl --color=always      # Ubuntu

For ls and other programs you may need to do other configuration, but that will show up even if you're not using watch.

Dennis Williamson
  • 346,391
  • 90
  • 374
  • 439
  • 3
    take a look at: http://superuser.com/questions/125469/bash-watch-command-with-colors-preserved (first answer) - Maybe you can link it in your answer. – aatdark Apr 11 '12 at 02:26
  • 33
    I came here to use `watch` with `git diff`. FWIW, to get that to work you have to pass in `--color=always` to `git diff` (e.g. `watch --color git diff --color=always`. – theabraham Mar 02 '15 at 16:20
  • 1
    For gpustat, "watch -n 1 --color gpustat --color" works. – Jungwon Choi Sep 25 '20 at 16:44
  • 3
    To show colors using `watch` with `git status` need to use `watch --color git -c color.status=always status`. See linked answer here https://unix.stackexchange.com/a/47065/268780. – Yuri Feldman Oct 31 '20 at 10:46
  • 1
    my watch claims to support --color (also -c) but the output is still black and white - even when using your exact example. – Al Ro Mar 09 '22 at 06:54
  • 1
    @AlRo, same issue on my side. Just curious, which OS are you on? I am seeing that issue on CentOS 7. – Spencer D Apr 15 '22 at 23:05
  • This also affects color of the terminal is it normal? – alper Apr 06 '23 at 11:34
  • @alper: Can you be more specific? What part of the terminal? Is it after you exit `watch` or while it's running? Which OS, distribution or window manager? Which terminal (xterm, gnome-terminal, Terminal.app)? What command line were you running within `watch`? – Dennis Williamson Apr 06 '23 at 13:29
58

Do not use watch ... When you use watch programs can detect they're not writing to a terminal and then strip the color. You must use specific program flags to keep the control codes there.

If you don't know the flags or there isn't you can make a poor's man watch by:

while sleep <time>; do clear; <command>; done

It will have a bit of flicker (watch works "double buffered") but for some stuff it is useful enough.

You may be tempted to make a double buffered poor man's watch using

while sleep <time>; do <command> > /tmp/file; clear; cat /tmp/file; done

But then you'll hit again the "I am not writing to a terminal" feature.

theist
  • 3,270
  • 2
  • 22
  • 23
  • Maybe use `while sleep – André Leria May 30 '17 at 16:58
  • mmm I don't get it @AndréLeria ... | tee will remove color codes like `watch` do and doesn't prevent command from flickering – theist May 31 '17 at 09:03
  • It is a suggestion for the second example, which also doesn't give me colors. Or maybe I'm doing something wrong? – André Leria May 31 '17 at 13:05
  • 1
    @AndréLeria The second "example" is a wrong example (As its said in the las line). The point is that once you hit a pipe you lose the color codes since you aren't writing to a terminal. It is there to show how wrong is to try to compensate the flicker due the time lapse between clear and the target command execution using a pipe to work buffered like `watch` – theist May 31 '17 at 13:26
  • 6
    In bash: `while sleep – Géza Török Sep 11 '17 at 13:29
  • 3
    @GézaTörök, yes but this also clear the color codes from the result output, which was the main concern of the user asking. – theist Sep 11 '17 at 16:10
  • @theist nope, variable `x` will hold special characters as well, except `\0`. Try this in bash-3.2 or later: `while true ; do x="$( echo -e "\e[31;01m" ; date ; echo -e "\e[0m" )" ; clear ; echo "$x" ; sleep .1 ; done` it will display red date :) – Géza Török Sep 13 '17 at 11:18
  • 1
    @GézaTörök Geez from some commands I tried works but others not... for example didnt work for `ls --la` (in my setup it adds colors by default) nor `ls | grep foo` nor `grep ^ *` nor `bundle exec knife status` but worked for `ls --color` maybe because --color forces color codes – theist Sep 15 '17 at 09:50
  • @theist sure, color codes must be emitted by the command. But when you are `watch`ing a command, does that process see so that it writes to a terminal? I don't think so. All the `grep` alternatives with `--color` added must work as well. – Géza Török Sep 15 '17 at 18:46
  • This'll keep blinking for short intervals. – j4hangir Sep 29 '20 at 13:54
  • The poor man's `watch` has the ~~bug~~ feature of also showing the history of previous invocations if you scroll up. – ijoseph Oct 11 '20 at 23:03
33

While other answers solve this problem, the easiest way to accomplish this is using the unbuffer tool. To use it simply do:

$ watch --color 'unbuffer <your-program>'

This way you don't have to hunt for control sequence enabling flags of your program. The caveat however is that your version of watch should support the --color flag.

You can install unbuffer on Debian or Ubuntu using sudo apt-get install expect.

lol
  • 506
  • 1
  • 5
  • 14
20

You can duplicate the fundamental, no-frills operation of watch in a couple lines of shell script.

$ cat cheapwatch 
#!/bin/sh

# Not quite your Rolex

while true ; do
  clear
  printf "[%s] Output of %s:\n" "$(date)" "$*"
  # "$@" <- we don't want to do it this way, just this:
  ${SHELL-/bin/sh} -c "$*"
  sleep 1  # genuine Quartz movement
done

$ ./cheapwatch ls --color  # no problem

Eventually, someone very clever will hack a tr command into this script which strips control characters, and then force the user to use --color to disable that logic. For the time being, the sheer naivete of this implementation is keeping the color-eating monster away.

If you're in a situation where watch doesn't have the --color option and you can't upgrade the package for whatever reason, maybe you can throw this in.

Kaz
  • 55,781
  • 9
  • 100
  • 149
8

YES

watch works with color output. it is part of the procps package (at least in debian) here is bugreport for your question http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=129334 where they answer, that you should update the procps package

e.g. with ubuntu 11.04 this package works http://packages.debian.org/wheezy/procps

tl;dr

update procps

davidDavidson
  • 270
  • 3
  • 5
5

Other answers might not work if the command does not have option to force color output. Or you might be lazy like me and do not want to browse manual for each command to find the correct setting. I tried a few different techniques:

The script command

Script command captures output as run by an interactive terminal session. With the combination of --color parameter of watch, it retains colors:

watch --color "script -q -c '<command>' /dev/null"

-q is for quiet, -c is for command and /dev/null is the log file, which is not needed as stdout also shows the output.

Edit: This is the best option so far, I left the earlier solution below for the interested.

Earlier try: Rewrite the terminal window

As suggested by some, a simple while loop with clear and sleep can be used to run the command in terminal without capturing its output. This usually causes flicker, as clear removes all characters and then the command take some time to print the new output line by line.

Fortunately, you can fix this with some clever terminal tricks using tput. Just leave the old output visible while writing the new on top.

Here is the script:

#!/bin/sh
trap "tput cnorm" EXIT  # unhide the cursor when the script exits or is interrupted

# simple interval parameter parsing, can be improved
INTERVAL=2s
case $1 in
  -n|--interval)
    INTERVAL="$2"
    shift; shift
  ;;
esac

clear           # clear the terminal
tput civis      # invisible cursor, prevents cursor flicker

while true; do
  tput cup 0 0  # move cursor to topleft, without clearing the previous output
  sh -c "$*"    # pass all arguments to sh, like the original watch
  tput ed       # clear all to the end of window, if the new output is shorter
  sleep "$INTERVAL"
done

The script fixes color problems, but a different bug remains: If the lines of the command output gets shorter, the rest of the line is not necessarily erased, so the output might not match with reality!

TK009
  • 51
  • 1
  • 5
  • This worked for me. I wanted to show taskboard (https://github.com/klaussinani/taskbook) tasks in a tmux popup window with `watch` and this helped. – Arpan Srivastava Aug 04 '22 at 07:53
2

From watch manual:

Non-printing characters are stripped from program output. Use "cat -v" as part of the command pipeline if you want to see them.

Though, I am not sure how to use it.

desertnaut
  • 57,590
  • 26
  • 140
  • 166
Benoit
  • 76,634
  • 23
  • 210
  • 236
  • 6
    This causes the control characters to be visible in the output for me, rather than causing colouration. For example `watch -c "ls --color|cat -v"` shows `^[[0m^[[01;34mAgent^[[0m` for the first line. – Drew Noakes Feb 20 '14 at 14:17
  • 2
    try `watch --color ls --color=always .` – Zhang LongQI Feb 11 '20 at 09:28
2

unbuffer is a great way to avoid letting process know if it is writing to TTY, but worth noting that watch does not support 8-bit colors and above yet.

If instead of ls you use something more modern like bat or exa, you should append --theme=ansi (not even --theme=base16 works). git log works out of the box because it always uses 3-bit colors (source).

Example:

watch --color -d -n 0.5 'mycommand file | bat --color=always --theme=ansi'

Could also use -f instead of --color=always.

Another alternative could be Pygments.

Pablo Bianchi
  • 1,824
  • 1
  • 26
  • 30