88

From man watch:

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

So how do I use cat -v if I want to see the colored output from:

watch ls -al --color
Paweł Gościcki
  • 2,728
  • 3
  • 23
  • 26

4 Answers4

99

The right command is

watch --color "ls -a1 --color"

It isn't documented in the man page or the --help screen. I has to use strings to find it.

paperhorse
  • 1,114
  • 8
  • 3
  • @PawełGościcki Nevermind, already found it on gitorious, although, couldn't get it to work with phpunit. – Ikke Jan 19 '12 at 13:11
  • 1
    My watch is v0.3.0 and I'm on Ubuntu 10.0 – Paweł Gościcki Jan 19 '12 at 14:00
  • 4
    I've also version 0.3.0 and for simple "ls --color" the watch command will work but for some reason more complex scenarios do not: `watch --color "sudo iwlist wlan0 scanning | egrep 'Quality|ESSID' | egrep --color -i 'foobar|$'"`will eat the colors :( – math Mar 07 '12 at 13:39
  • @math: Try swapping your single and double quotes. – Dennis Williamson Apr 11 '12 at 11:03
  • The `watch` from procps (the default on most Linux distros, I believe) has a `--color` option since V3.3.2. – sleske Sep 04 '13 at 22:43
  • 1
    Note that the version 3.3.2 is only available in procps-ng, original procps.sf.net seems development has stopped years ago (version is still 3.2.8 and watch version 0.2.0). Also note to OSX/Darwin users the new and maintained fork of procps-ng doesn't yet compile on OSX using LLVM (see https://github.com/Homebrew/homebrew/pull/20845). – bric3 Jan 07 '14 at 16:07
  • 1
    How do you update your watch version? – Adam Hunyadi May 19 '17 at 20:47
  • 1
    It's documented in the man page & help screen of 3.3.16 that I got from Homebrew on macOS (`watch --version` => `watch from procps-ng 3.3.16`). `watch --help` => `-c, --color interpret ANSI color and style sequences`. Guessing they must have updated the documentation in newer versions. – M. Justin Apr 24 '20 at 17:18
32

I think it may not be possible with the 'watch' command. Here is a longer way of doing it:

while true; do clear; date;echo;ls -al --color; sleep 2; done

You could put this in a script, for example:

echo "while true; do clear; date;echo;\$*;sleep 2; done" > watch2
chmod +x watch2
./watch2 ls -al --color

To clarify, here's why I think it's not possible with the 'watch' command. See what happens if you use cat -v:

watch "ls -al --color|cat -v"

It shows you the color control characters...which I think is not what you want.

davr
  • 5,368
  • 7
  • 37
  • 46
  • `man watch` clearly suggests that it should be possible without dissing `watch`. – Paweł Gościcki Mar 29 '10 at 19:27
  • It doesn't say you will be able to see colors. It says you will be able to see the non-printable characters. Try my command as above with `cat -v` to see what `man watch` was talking about. – davr Mar 29 '10 at 20:03
  • OK. It seems I must accept the fact that it's simply impossible. – Paweł Gościcki Mar 31 '10 at 15:37
  • Is there a way to suppress the blinking that results from the cycles of clear and print operations, a behavior not present in the `watch` command? – user001 Oct 01 '16 at 02:43
  • 1
    You can reduce the duration of the blink a little by a) collecting the data to be displayed into a variable, b) clearing the screen, c) printing the variable. – Nick Russo Dec 13 '16 at 18:21
  • 1
    @NickRusso thanks for the suggestion. Something like this greatly reduces the flickering: `while true; do out=$(date;echo;ls -al --color);clear;echo $out;sleep 2;done` – Kevin Mark Jul 23 '17 at 14:21
  • Also consider trimming line length to fit in terminal: https://superuser.com/a/58812/114579 – Brent Bradburn Sep 15 '17 at 21:18
  • 1
    @KevinMark: You should use quotes to handle multiple lines: `echo "$out"`. https://stackoverflow.com/q/2414150/86967 – Brent Bradburn Sep 15 '17 at 21:20
  • @nobar You're right. Looks like it needs quotes in bash not not zsh. – Kevin Mark Sep 15 '17 at 21:27
  • @KevinMark You can put the "clear" command inside the parentheses. It just prints a terminal control code. See also my longer answer https://superuser.com/a/1270584/21952. – user21952-is-a-great-name Nov 21 '17 at 20:57
  • This'll blink for short intervals. – j4hangir Sep 29 '20 at 13:57
  • This is the solution that worked for me with commands like `gh pr status` to monitor checks status from the command line. – ryuzakyl Aug 14 '23 at 17:32
7

If you're using a Mac, like me, watch from Homebrew does not support colour.

What you want is fswatch but it's not Homebrew yet. To install it you'll want to do the slightly more convoluted

https://raw.github.com/mlevin2/homebrew/116b43eaef08d89054c2f43579113b37b4a2abd3‌​/Library/Formula/fswatch.rb

See this SO answer for usage.

fatuhoku
  • 252
  • 1
  • 3
  • 10
  • 2
    This only works for the filesystem, while `watch` applies to a command – bric3 Jan 07 '14 at 15:49
  • 1
    fswatch is available on Homebrew 0.9.5 – code_monk Oct 20 '14 at 01:45
  • The Homebrew version of watch now supports color using the `--color` flag mentioned in [this answer](https://superuser.com/a/211590/110370). `watch --version` => `watch from procps-ng 3.3.16`. – M. Justin Apr 24 '20 at 17:22
3

UPDATE: Turns out the latest versions of watch fixed the problem. So, if the colors of watch --color are wrong, it's probably better to just update it (on my system, it's in the procps package).


The color support in watch --color is limited in my experience (though sufficient for ls -l --color). Here's my version of @davr's answer with some extra features, most importantly reduced flicker. You can put it in your .bashrc and use it as cwatch ls -l --color.

# `refresh cmd` executes clears the terminal and prints
# the output of `cmd` in it.
function refresh {
  tput clear || exit 2; # Clear screen. Almost same as echo -en '\033[2J';
  bash -ic "$@";
}

# Like watch, but with color
function cwatch {
   while true; do
     CMD="$@";
     # Cache output to prevent flicker. Assigning to variable
     # also removes trailing newline.
     output=`refresh "$CMD"`;
     # Exit if ^C was pressed while command was executing or there was an error.
     exitcode=$?; [ $exitcode -ne 0 ] && exit $exitcode
     printf '%s' "$output";  # Almost the same as echo $output
     sleep 1;
   done;
}

You can also try things like

cwatch 'ls -l --color | head -n `tput lines`'

if your terminal has fewer lines than the output. That only works if all the lines are shorter than the terminal width, though. The best workaround I know for that is:

cwatch 'let lines=`tput lines`-2; ls -l --color | head -n $lines'