如何将标准输入设为终端(tty)?

3

有些程序会根据stdout是否为tty来改变它们的输出。因此,如果您将这些程序放入管道中或进行重定向,则输出与在shell中的输出不同。这是一个例子:

$ touch a b c

# when running ls alone, it places them on one line
$ ls
a b c

# when stdout is not a tty, it places them on their own line
$ ls > output

$ cat output
a
b
c
output

所以,如果我想向某人展示这样一个命令应该是什么样子的(例如,我正在撰写教程),我必须突出显示并复制终端输出,然后保存到文件中。看起来我应该能够做这样的事情:
ls | ttypipe > output

ttypipe 是一个虚构的程序,当询问其是否为 tty 时,它的标准输入(因此也是 ls 的标准输出)会返回 true。

我知道在 Ruby 中,我可以像这样做:

require 'pty'         # => true
IO.pipe.map(&:tty?)   # => [false, false]
PTY.open.map(&:tty?)  # => [true, true]

但这只是针对子进程,而不是当前进程,因此:

$stdin.tty?  # => false

我可以执行exec命令,但是我无法想到一种方法来影响stdin文件描述符。


$stdin.tty?(不需要任何参数,使用IO#tty?)返回true - steenslag
1个回答

3

你不能写ttypipe,因为管道是管道,永远不可能是tty。然而,你可以使用稍微不同的语法编写一个ttyexec

ttyexec ls > output

它会打开一个伪终端,运行ls命令,并将ls命令在终端上写的任何内容复制到ttyexec的标准输出中。
惊奇地发现,已经有一个类似的工具: script。它会在新的隐藏pty中打开一个程序以记录与其的交互,但我们可以忽略记录部分,只使用其终端打开属性。
$ touch a b c

$ ls
a  b  c

$ script -q -c 'ls' /dev/null > output

$ cat output 
a  b  c  output

1
谢谢。这就是我最终实现它的方式 https://github.com/JoshCheek/dotfiles/compare/84a7b01c58aa3ee3ba8a93f9199c1375e3671894...10f801b1e82205dcffd40a4f5c9402b857368929 - Joshua Cheek

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