在bash中模拟成tty,用于执行任何命令。

45
每当我使用grep并将其管道到另一个程序时,--color选项都不会被执行。 我知道我可以使用--color=always,但它也会在我想要获得与在tty中获得的相同输出的一些其他命令中出现。
所以我的问题是,有没有可能欺骗一个命令,让它认为该命令是在tty中运行的?
例如,运行
grep --color word file # Outputs some colors
grep --color word file | cat # Doesn't output any colors

我希望能够写出类似以下的内容:

我想要实现这样的功能:

IS_TTY=TRUE grep --color word file | cat  # Outputs some colors

这个问题似乎有一个可以满足我要求的工具:empty - 在伪终端(PTY)下运行进程和应用程序,但是根据我在文档中所读到的内容,我不确定它是否能够解决我的问题。


1
你意识到 --color 会改变发送到管道下游命令的实际数据流吗?这将导致其他合理的代码出现问题,因为 searchTarget 不是 ^[32;4gsearchTarget^[32;h(或类似的内容)。祝好运。 - shellter
1
是的,我意识到了。在我的脚本中,我永远不会使用这种技术来着色 greps,但是我使用的一些命令似乎在在 tty 外部使用时输出了一些不同的东西(例如 ag,the silversearcher,还有 mocha 等等...),而且我没有时间学习所有选项以相同的格式打印它们,每当我将这些命令管道传递给其他命令时。 - edi9999
嗯...我认为这个问题以前已经出现过,而且给了我一些惊人的答案。你搜索过 [linux] (or) [bash] --color 吗?祝你好运。 - shellter
我搜索了一下,但没有找到任何解决我的问题的东西。 - edi9999
3
你尝试过这些方法中的任何一个吗?它们分别是:https://dev59.com/dXM_5IYBdhLWcg3wZSE6https://dev59.com/JG855IYBdhLWcg3woV4_http://rachid.koucha.free.fr/tech_corner/pty_pdip.html - Carlos Porta
1个回答

48

有一些选项,如其他 Stack Overflow 答案所述(请参见Caarlos评论)。但我在这里总结一下:

  1. 使用script + printf,不需要额外的依赖项:

 0<&- script -qefc "ls --color=auto" /dev/null | cat

或者创建一个bash函数faketty来封装它:

 faketty () {
     script -qefc "$(printf "%q " "$@")" /dev/null
 }
 faketty ls --color=auto | cat  

或者在 fish shell 中:

 function faketty
     script -qefc "(printf "%q " "$argv")" /dev/null
 end
 faketty ls --color=auto | cat 

(感谢这个答案)

http://linux.die.net/man/1/script

  • 使用unbuffer命令(作为expect命令套件的一部分)。不幸的是,这需要安装一个额外的软件包,但它是最简单的解决方案:

     sudo apt-get install expect-dev   # or brew install expect
     unbuffer -p ls --color=auto | cat  
    

    或者如果您使用 fish shell:

     function faketty
         unbuffer -p $argv
     end
     faketty ls --color=auto | cat 
    

    http://linux.die.net/man/1/unbuffer

    这是一篇关于TTY的工作原理以及伪终端(PTYs)的文章,如果您想了解Linux shell如何使用文件描述符传递输入、输出和信号,那么它值得一看。 http://www.linusakesson.net/programming/tty/index.php


  • 2
    script 后面添加 -e 可以返回命令的返回值。此外,考虑使用管道符号连接到 less -FXur,这将显示颜色,并且如果输出适合单个屏幕,则不会执行任何操作(并修复 \r 问题,如果有的话)。 - Tom Hale
    4
    交换 c 和 e 的位置script -qfec "$(printf "%q " "$@")" - Erik Martino
    2
    请参考 https://dev59.com/dXM_5IYBdhLWcg3wZSE6#60279429,该版本适用于Linux和MacOS,并支持返回状态码。 - Jonas Berlin
    1
    这个答案应该是写得有一段时间了,但是我刚刚检查了在ArchLinux上安装“expect”的大小,它不到1MB的一半。 - smac89
    1
    关于选项1,我建议保留原始答案中的/dev/null部分,否则你最终会生成一个带有一些你可能不需要或甚至不想要的内容的typescript文件。 - drmrbrewer
    显示剩余13条评论

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