使用Unix命令"watch"显示彩色输出?

187

我使用一些命令来显示颜色,但是当我在watch命令中使用它们时,颜色会消失:

watch -n 1 node file.js

有没有办法重新显示出颜色?


可能是如何使watch命令解释vt100序列?的重复问题。 - l0b0
8个回答

230
一些较新版本的watch现在支持颜色。
例如:watch --color ls -ahl --color相关链接
如果您期望看到彩色输出时,看到的是单色的输出,则很可能是您在watch内运行的命令检测到它未连接到终端,您需要强制输出颜色。以下是一些示例:
CLICOLOR_FORCE=1 watch --color ls -ahl    # MacOS
watch --color ls -ahl --color=always      # Ubuntu

对于ls和其他程序,您可能需要进行其他配置,但即使您不使用watch,也会显示出来。


3
请查看:http://superuser.com/questions/125469/bash-watch-command-with-colors-preserved(第一个答案)-也许你可以在你的答案中提供链接。 - aatdark
33
我来这里是为了使用 watch 命令查看 git diff 的结果。顺便提一下,为了让它正常工作,你需要在执行 git diff 命令时传入 --color=always 参数(例如:watch --color git diff --color=always)。 - theabraham
3
要在使用git status命令时通过watch显示颜色,需要使用以下命令:watch --color git -c color.status=always status。请参考此处链接的答案:https://unix.stackexchange.com/a/47065/268780。 - Yuri Feldman
1
我的手表声称支持--color(也可以是-c),但输出仍然是黑白的,即使使用您的确切示例。 - Al Ro
1
@AlRo,我这里也遇到了同样的问题。不知道你用的是哪个操作系统?我在CentOS 7上遇到了这个问题。 - Spencer D
显示剩余3条评论

58

请勿使用watch命令......当您使用watch命令时,程序会检测到它们没有写入终端,并将去除颜色。您必须使用特定的程序标志来保留控制代码。

如果您不知道这些标志或者没有这样的标志,你可以通过以下方法创建一个简单的watch命令替代品:

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

这款手表会有一点闪烁(手表采用“双缓冲”),但对于某些情况下,它还是足够有用的。

你可能会尝试使用双缓冲技术制作一个简易手表。

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

然后你会再次遇到“我不是在写入终端”的功能。


我不明白 @AndréLeria 的意思... | tee 命令会移除类似 watch 的颜色代码,并且不会防止命令闪烁。 - theist
1
@AndréLeria 第二个“示例”是错误的示例(正如最后一行所说)。关键是,一旦你碰到一个管道,你就失去了颜色代码,因为你不是在写入终端。它在那里展示了试图通过使用类似于“watch”的缓冲区来补偿清除和目标命令执行之间的时间间隔而尝试使用管道的错误方法。 - theist
6
在bash中: while sleep <时间> ; do x="$( <命令> 2>&1 )" ; clear ; echo "$x" ; done -- 它只使用shell内置函数来清除屏幕和显示输出,因此是最不闪烁的替代方案。 - Géza Török
3
@GézaTörök,是的,但这也会清除结果输出中的颜色代码,这是提问用户的主要关注点。 - theist
1
@GézaTörök 你好,我尝试了一些命令,有些可以正常工作,但有些不行...例如对于 ls --la(在我的设置中默认添加颜色),ls | grep foogrep ^ *bundle exec knife status 都无法正常工作,但是对于 ls --color 可以正常工作,可能是因为 --color 强制使用颜色代码。 - theist
显示剩余6条评论

34

虽然其他答案解决了这个问题,但最简单的方法是使用unbuffer工具。只需执行以下操作即可:

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

这样您就无需搜寻程序的控制序列启用标志。不过,需要注意的是您的 watch 版本需支持 --color 标志。

您可以使用 sudo apt-get install expect 在 Debian 或 Ubuntu 上安装 unbuffer。


3
只有你得到了我的点赞。所有其他更高票的回答都给了我帮助。但是这个才有效果。 - Antoni
2
这应该是被接受的答案。 - jibiel
在 macOS 上输入 brew install expect - ijoseph

20
你可以在几行shell脚本中复制watch的基本操作,不需要花哨的功能。
$ 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

最终,有些非常聪明的人会将 tr 命令嵌入到这个脚本中,以剥离控制字符,然后强制用户使用 --color 来禁用该逻辑。目前,这种实现的天真程度使得吞噬颜色的怪物远离它。
如果你处于一个没有 --color 选项并且由于某种原因不能升级包的情况下,也许你可以尝试使用这个方法。

8

6

如果命令没有强制输出彩色的选项,其他答案可能无效。或者您可能像我一样懒,不想为每个命令浏览手册以找到正确的设置。我尝试了几种不同的技术:

script命令

script命令会捕获交互式终端会话运行的输出。结合watch命令的--color参数,它可以保留颜色:

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

-q 代表安静模式,-c 代表命令,/dev/null 是日志文件,不需要作为 stdout 已经显示了输出。

编辑:这是迄今为止最好的选择,我将早期的解决方案保留下来给有兴趣的人。

早期尝试:重写终端窗口

正如一些人建议的那样,可以使用带有 clearsleep 的简单 while 循环在终端中运行命令而不捕获其输出。这通常会导致闪烁,因为 clear 删除所有字符,然后命令需要一些时间逐行打印新的输出。

幸运的是,你可以使用一些巧妙的终端技巧,使用 tput 在写入新内容时保留旧的输出可见。

以下是脚本:

#!/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

该脚本修复了颜色问题,但仍存在另一个错误:如果命令输出的行变短,剩余部分未必被擦除,因此输出结果可能与实际不符!

这对我很有用。我想在一个tmux弹出窗口中使用watch显示taskboard(https://github.com/klaussinani/taskbook)任务,这很有帮助。 - Arpan Srivastava

2
"unbuffer是一个很好的方法,可以避免让进程知道它是否正在写入TTY,但值得注意的是,watch目前还不支持8位色和以上。"
"如果你使用的不是ls,而是一些更现代的东西,比如batexa,那么你应该添加--theme=ansi(甚至--theme=base16也不行)。git log可以直接使用,因为它总是使用3位颜色(来源)。"
"例如:"
watch --color -d -n 0.5 'mycommand file | bat --color=always --theme=ansi'

也可以使用-f代替--color=always
另一个选择是Pygments

这有点令人沮丧,因为它还不能与kubecolor配合使用。 - tbrodbeck

2

来自手表使用手册:

程序输出中的非打印字符会被过滤掉。如果您想看到它们,请在命令管道中使用 "cat -v"。

但是,我不确定该如何使用它。


6
这会导致控制字符在我的输出中可见,而不是引起颜色变化。例如,watch -c "ls --color|cat -v" 对于第一行显示为 ^[[0m^[[01;34mAgent^[[0m - Drew Noakes
2
尝试运行 watch --color ls --color=always . 命令。 - Zhang LongQI

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接