可以通过 shell 重定向捕获彩色输出吗? [复制]

Posted

技术标签:

【中文标题】可以通过 shell 重定向捕获彩色输出吗? [复制]【英文标题】:Can colorized output be captured via shell redirect? [duplicate] 【发布时间】:2011-03-31 17:19:29 【问题描述】:

我使用的各种 bash 命令——花哨的差异、构建脚本等,会产生大量的颜色输出。

当我将此输出重定向到一个文件,然后 catless 文件稍后,着色消失了——大概是 b/c 重定向输出的行为去除了告诉终端的颜色代码改变颜色。

有没有办法捕获彩色输出,包括着色?

【问题讨论】:

大声笑@骗子通知:“如何欺骗应用程序认为它的标准输出是终端,而不是管道”似乎与“可以通过 shell 重定向捕获彩色输出吗?" 【参考方案1】:

捕获彩色输出的一种方法是使用script 命令。运行 script 将启动一个 bash 会话,其中所有原始输出都被捕获到一个文件中(默认命名为 typescript)。

【讨论】:

一个例子:script -q /dev/null ls | cat 这会导致生成的文件包含颜色代码(当然);有什么方法可以使用颜色代码打印文件并在终端中正确显示颜色?我试过echo -e $(< filename),但这似乎不起作用。 ....实际上,echo -e $(< filename ) 确实 似乎对输出进行了着色,但由于某种原因,输出的第一部分似乎被 Script done on <DATE> 遮盖了。 有一个名为 ansi2html 的脚本可以很好地将生成的打字稿转换为 HTML。 另一个例子:script<enter for new shell> lolcat /etc/motd > /tmp/color_motd 然后编辑typescript 文件并根据需要去掉开始和结束输出。【参考方案2】:

重定向不会去除颜色,但许多命令会检测它们何时将输出发送到终端,如果没有,默认情况下不会产生颜色。例如,在 Linux 上,ls --color=auto(在很多地方别名为普通的ls)如果输出到管道或文件不会产生颜色代码,但ls --color 会。许多其他工具都有类似的覆盖标志,可以让它们将彩色输出保存到文件中,但它们都是特定于单个工具的。

即使您在文件中有颜色代码,要查看它们,您也需要使用保持它们完整的工具。 less 有一个 -r 标志以“原始”模式显示文件数据;这将显示颜色代码。 edit: 稍新的版本也有一个 -R 标志,它特别了解颜色代码并正确显示它们,比原始模式更好地支持换行/修剪等内容,因为更少的东西可以分辨出哪些是控制代码和哪些实际上是进入屏幕的字符。

【讨论】:

ls --colorls --color=always 相同 - 您正在考虑 ls --color=auto ⁺¹,您刚刚解决了我们关于是应用程序确定它是否重定向到文件,还是外壳本身在重定向时负责剥离颜色 ANSI 符号的讨论。【参考方案3】:

受其他答案的启发,我开始使用script。我不得不使用-c 让它工作。所有其他答案,包括tee,不同的script 示例对我都不起作用。

上下文:

Ubuntu 16.04 使用behave 运行行为测试并在测试期间使用python 的subprocess.check_call() 启动shell 命令

解决方案:

script --flush --quiet --return /tmp/ansible-output.txt --command "my-ansible-command"

开关说明:

--flush 是必需的,因为否则输出不能很好地实时观察,以大块的形式出现 --quiet 抑制脚本工具自己的输出 -c, --command 直接提供要执行的命令,从我的命令到脚本的管道对我不起作用(没有颜色) --return 让脚本传播我的命令的退出代码,以便我知道我的命令是否失败

【讨论】:

最佳答案!谢谢。 我喜欢它甚至可以与参数一起使用。要在仍写入文件时禁止终端输出,请将> /dev/null 添加到命令末尾 (script --flush --quiet --return /tmp/ansible-output.txt --command "my-ansible-command" > /dev/null)。 添加-a 标志以追加到日志文件。【参考方案4】:

我发现使用script 在管道到less 时保留颜色并不能真正起作用(less 全部搞砸了,退出时,bash 搞砸了),因为 less 是交互式的。 script 似乎真的把来自stdin 的输入弄乱了,即使在退出之后也是如此。

所以不要运行:

script -q /dev/null cargo build | less -R

我将 /dev/null 重定向到它,然后再通过管道传输到 less:

script -q /dev/null cargo build < /dev/null | less -R

所以现在script 不会与stdin 混淆,并得到我想要的。它相当于command | less,但它保留了颜色,同时还继续读取附加到文件的新内容(我尝试过的其他方法不会这样做)。

【讨论】:

顺便说一句,只要管道在运行,script 就不会退出。所以在你上面的第一个命令(实际上是两个)中,直到less 退出它才会退出。 这很棒。对我来说,一个主要用例是读取比我的屏幕高度高的彩色 grep 输出,除非使用像 less 这样可以让我连贯滚动的阅读器,否则这没有任何意义。 关于如何让它与 shell 函数一起工作的任何想法?它似乎不适用于他们。我得到命令未找到或什么都没有。 @MrE 否,因为script 是可执行文件,因此它无法访问您的 shell 函数。您需要将它们包装在独立的脚本中。 更容易使用unbuffer,当管道到less和其他交互式命令时可以使用:***.com/a/1410273【参考方案5】:

当某些程序意识到输出不是 TTY 时(即当您将它们重定向到另一个程序时),它们会移除着色。您可以告诉其中一些强制使用颜色,并告诉寻呼机打开着色,例如使用less -R

【讨论】:

【参考方案6】:

当我的other answer(涉及tee)不起作用时,超级用户上的This question 帮助了我。它涉及使用unbuffer 使命令认为它是从shell 运行的。

我使用 sudo apt install expect tcl 而不是 sudo apt-get install expect-dev 安装它。

讽刺的是,我在重定向apt的输出时需要使用这种方法。

【讨论】:

【参考方案7】:

我使用tee:将命令的输出通过管道传输到teefilename,它会保持颜色。如果您不想在屏幕上看到输出(这就是tee 的用途:同时显示和重定向输出),那么只需将tee 的输出发送到/dev/null

command| teefilename&gt; /dev/null

【讨论】:

您使用的tee 的版本是什么? tee 8.21(Ubuntu 14.04 附带)默认情况下似乎不会对输出进行着色(在虚拟程序中使用 cmake + make 测试)。 我刚刚在两台机器上测试过,一台使用 tee 8.21,一台使用 tee 8.25。两者都有效。我做了echo "^[[32mhello^[[0m" | tee temp.txt &gt; /dev/null(其中^[是转义字符),然后使用catod -c检查temp.txt 您希望它如何工作?程序只能判断它正在向 FIFO 发送内容——它无法判断该 FIFO 是否有 tee 或它后面的任何其他特定程序。因此,如果该程序配置为仅直接向 TTY 发出颜色,到tee 的管道将像到任何其他程序的管道一样破坏它。 这不是理论上的答案:我已经使用成功了!我不知道它是如何工作的,但它对我来说是一个简单的重定向失败的地方。 这绝对不适用于问题的目的。这仅在直接回显上述 cmets 中所述的颜色时才有效,因为这不会检查终端是否具有颜色能力,而只会回显所要求的任何内容。 tee 确实会更改终端并影响检查它的程序,终端是交互式的,就像简单的直接一样。

以上是关于可以通过 shell 重定向捕获彩色输出吗? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

shell输入输出重定向

Linux Gvim shell 输入输出重定向

小鸟初学Shell编程输入输出重定向

Linux shell之重定向

关于shell输入 输出重定向

Linux Shell系列教程之(十六) Shell输入输出重定向