2014-07-19 27 views
1

只是为了好玩,我想将终端中的所有输出文本管到espeak。例如,在设置完成后,我应该能够输入echo hi,并听到“hi”说话,或者ls,并听取我列出的目录内容。钩住bash中的所有命令输出

唯一有前途的方法来捕获输出到目前为止,我发现就是从这里开始:http://www.linuxjournal.com/content/bash-redirections-using-exec

这是我到目前为止有:

npipe=/tmp/$$.tmp 
mknod $npipe p 
tee /dev/tty <$npipe | espeak & 
espeakpid=$! 
exec 1>&- 
exec 1>$npipe 
trap "rm -f $npipe; kill $espeakpid" EXIT 

它的工作原理(也打印了一堆“完成“工作),但创建命名管道,删除陷阱和打印输出tee都显得有点混乱。有一种更简单的方法吗?

+1

只有挂钩所有命令输出很容易与'exec>>(tee bash.log)'。但是正确处理终端,IPC(无需填写文件)等。以上是正确的方法。 – jm666

+0

@ jm666谢谢,有没有办法用管道而不是文件重定向? – jozxyqk

回答

2

这是一种方式:

exec > >(exec tee >(exec xargs -n 1 -d '\n' espeak -- &>/dev/null)) 

如果你希望能够恢复回原来的输出流:

exec 3>&1 ## Store original stdout to fd 3. 
exec 4> >(exec tee >(exec xargs -n 1 -d '\n' espeak -- &>/dev/null)) ## Open "espeak" as fd 4. 
exec >&4 ## Redirect stdout to "espeak". 
exec >&3 ## Redirect back to normal. 
  • 我用xargs -n 1因为espeak达到EOF直到没有做任何事情,所以我们召唤它每行一个实例。这当然可以定制,但你的答案是。当然,while read循环也可以作为此选项。
  • 我也使用exec进行过程替换,以确保我们摆脱不必要的子壳体。
0

好像它比这样更容易 - 我只是测试这一点,它的工作原理:

$ echo "these are not the droids you are looking for" | espeak --stdin 

--stdin标志是关键。从espeak的手册页:

--stdin 
      Read text input from stdin instead of a file 

如果你想听到的是一个很长的输出,我想你可以使用xargs如果碰上参数列表太长错误.. 。

+0

我很舒服地管道espeak(如我已经在我的例子)。问题我让它捕获bash shell中任何命令的输出,也不会干扰输出本身。例如'bash | tee/dev/tty | espeak',不幸的是这创造了一个我更喜欢避免的新壳。 – jozxyqk