Can colorized output be captured via shell redirect?
我使用的各种bash命令——花哨的diff、构建脚本等,会产生大量的颜色输出。
当我将这个输出重定向到一个文件,然后cat或less文件之后,着色就消失了——大概是b/c重定向输出的行为去掉了告诉终端更改颜色的颜色代码。
有没有一种方法来捕获彩色输出,包括彩色化?
捕获彩色输出的一种方法是使用script命令。运行script将启动一个bash会话,在该会话中,所有原始输出都被捕获到一个文件中(默认情况下名为typescript)。
- 例如:script -q /dev/null ls | cat。
- 这会导致生成的文件包含颜色代码(当然);是否有任何方法可以使用颜色代码并正确显示终端中的颜色来打印该文件?我试过echo -e $(< filename),但似乎没用。
- ….实际上,echo -e $(< filename )似乎确实对输出着色,但出于某种原因,输出的第一部分似乎被Script done on 遮盖了。
- 有一个名为ansi2html的脚本可以很好地将生成的typescript转换为html。
- 另一个例子:script lolcat /etc/motd > /tmp/color_motd,然后编辑typescript文件,根据需要删除开始和结束输出。
- 除非添加更复杂的重定向,否则script不工作,无法通过管道传输到交互命令,如less。更容易使用unbufferstackoverflow.com/a/1410273
重定向不会去除颜色,但许多命令将在向终端发送输出时进行检测,如果不这样做,则默认情况下不会生成颜色。例如,在Linux上,如果输出到管道或文件,EDOCX1(在很多地方别名为plain ls)将不会生成颜色代码,但ls --color将生成颜色代码。许多其他工具都有类似的覆盖标志,可以让它们将彩色输出保存到文件中,但这些标记都是特定于单个工具的。
即使你在一个文件中有颜色代码,要想看到它们,你需要使用一个保持它们完整的工具。less有一个-r标志,以"原始"模式显示文件数据;显示颜色代码。编辑:稍微更新一点的版本也有一个-r标志,它特别了解颜色代码并正确显示它们,比原始模式更好地支持换行/剪裁等操作,因为很少有人能分辨出哪些是控制代码,哪些实际上是要进入屏幕的字符。
- ls --color和ls --color=always是一样的,你想的是ls --color=auto。
- 很好的捕捉;编辑以修复。
- ?¹;,您刚刚解决了我们关于它是应用程序确定它是重定向到文件的讨论,还是当重定向处理除去颜色的ANSI符号时外壳本身的讨论。
受其他答案的启发,我开始使用script。不过,我不得不用-c让它工作。所有其他答案,包括tee,不同的script例子对我来说都不起作用。
语境:
- Ubuntu 16.04
- 使用behave运行行为测试,并在使用python的subprocess.check_call()测试期间启动shell命令。
解决方案:
1
| script --flush --quiet --return /tmp/ansible-output.txt --command"my-ansible-command" |
开关说明:
- 需要--flush,因为否则输出就不能很好地进行实时观测,而是成批出现。
- --quiet支持脚本工具的自己输出
- -c, --command直接提供要执行的命令,从我的命令到脚本的管道不适合我(没有颜色)
- --return使脚本传播我的命令的退出代码,这样我就知道我的命令是否失败了。
当一些程序意识到输出不是tty时(即当您将其重定向到另一个程序时),它们会取消着色。您可以告诉其中一些人强制使用颜色,并告诉寻呼机启用着色,例如使用less -R。
- 谢谢大家。这是一个很好的信息,并澄清了很多实际发生的事情。我忘记了脚本命令…它完全符合我的需要!
我发现使用script来保留管道到less时的颜色并不能真正起作用(越少,就越混乱,退出时,bash就越混乱),因为交互越少。script似乎真的把来自stdin的输入搞乱了,即使在退出之后。
因此,不要运行:
1
| script -q /dev/null cargo build | less -R |
我将/dev/null改向它,然后再改为:
1
| script -q /dev/null cargo build < /dev/null | less -R |
所以现在,script并没有和stdin搞混,而是得到了我想要的东西。它相当于command | less,但它保留了颜色,同时继续读取附加到文件中的新内容(我尝试的其他方法不会这样做)。
- 顺便说一下,只要管道运行,script就不会退出。所以,在上面的第一个命令中(实际上是两个命令),它直到less执行后才会退出。
- 这太好了。对于我来说,一个主要的用例是阅读比屏幕高度高的彩色grep输出,除了像less这样可以让我连贯滚动的阅读器之外,这并没有真正意义。
- 你知道如何让它与shell函数一起工作吗?这似乎对他们不起作用。我得不到命令或者什么都没有。
- @MRE否,因为script是一个可执行文件,所以它不能访问shell函数。您需要用独立的脚本包装它们。
- 使用unbuffer更容易,它在管道连接到less和其他交互命令时起作用:stackoverflow.com/a/1410273
当我的另一个答案(涉及tee)不起作用时,这个关于超级用户的问题帮助了我。它包括使用unbuffer使命令认为它是从shell运行的。
我用sudo apt install expect tcl而不是sudo apt-get install expect-dev安装它。
讽刺的是,我需要在重定向apt的输出时使用这种方法。
我使用tee:将命令的输出通过管道传输到teefilename,它将保持颜色。如果您不想在屏幕上看到输出(这就是tee的作用:同时显示和重定向输出),那么只需将tee的输出发送到/dev/null即可:
command| teefilename> /dev/null。
- 你用的tee的版本是什么?默认情况下,tee 8.21(随Ubuntu14.04一起提供)似乎不会对输出着色(在虚拟程序中用cmake+make测试)。
- 我刚在两台机器上测试过它,一台带有tee 8.21,另一台带有tee 8.25。两者都有效。我做了echo"^[[32mhello^[[0m" | tee temp.txt > /dev/null(其中^[是转义符),然后用cat和od -c检查temp.txt。
- 你希望这个怎么做?程序只能告诉FIFO它正在发送内容——它不能告诉FIFO背后是否有tee或任何其他特定的程序。因此,如果该程序被配置为只直接向tty发出颜色,那么到tee的管道将中断它,就像到任何其他程序的管道一样。
- 这不是一个理论上的答案:我已经成功地使用了它!我不知道它是如何工作的,但是在一个简单的重定向失败的地方,它确实对我有用。
- 这显然不适用于这个问题。这只在直接回显上面评论中所说的颜色时有效,因为这不检查终端是否具有颜色能力,而只是回显任何要求的颜色。tee确实改变了终端并影响了检查它的程序。终端的交互方式与简单的直接方式相同。