我如何从一个shell脚本中检测,如果它的标准输出被发送到终端或如果它被管道到另一个进程?
举个例子:我想添加转义码来着色输出,但只在交互运行时,而不是在管道运行时,类似于ls——color。
我如何从一个shell脚本中检测,如果它的标准输出被发送到终端或如果它被管道到另一个进程?
举个例子:我想添加转义码来着色输出,但只在交互运行时,而不是在管道运行时,类似于ls——color。
当前回答
你没有提到你在使用哪个shell,但是在Bash中,你可以这样做:
#!/bin/bash
if [[ -t 1 ]]; then
# stdout is a terminal
else
# stdout is not a terminal
fi
其他回答
在纯POSIX shell中,
if [ -t 1 ] ; then echo terminal; else echo "not a terminal"; fi
返回"terminal",因为输出被发送到您的终端,而
(if [ -t 1 ] ; then echo terminal; else echo "not a terminal"; fi) | cat
返回“非终端”,因为插入元素的输出被管道传输给cat。
-t标志在手册页中描述为
-t fd如果打开文件描述符fd并指向终端,则为True。
... fd可以是常见的文件描述符赋值之一:
0:标准输入 1:标准输出 2:标准误差
命令test(内置在Bash中)有一个选项来检查文件描述符是否是tty。
if [ -t 1 ]; then
# Standard output is a tty
fi
参见“man test”或“man bash”,搜索“-t”。
你没有提到你在使用哪个shell,但是在Bash中,你可以这样做:
#!/bin/bash
if [[ -t 1 ]]; then
# stdout is a terminal
else
# stdout is not a terminal
fi
下面的代码(仅在Linux Bash 4.4中测试)不应该被认为是可移植的,也不推荐,但为了完整性,这里是:
ls /proc/$$/fdinfo/* >/dev/null 2>&1 || grep -q 'flags: 00$' /proc/$$/fdinfo/0 && echo "pipe detected"
我不知道为什么,但当Bash函数具有标准输入管道时,似乎以某种方式创建了文件描述符“3”。
在Solaris上,来自Dejay Clayton的建议最有效。-p没有按期望的方式响应。
bash_redir_test.sh文件如下:
[[ -t 1 ]] && \
echo 'STDOUT is attached to TTY'
[[ -p /dev/stdout ]] && \
echo 'STDOUT is attached to a pipe'
[[ ! -t 1 && ! -p /dev/stdout ]] && \
echo 'STDOUT is attached to a redirection'
在Linux上,它工作得很好:
:$ ./bash_redir_test.sh
STDOUT is attached to TTY
:$ ./bash_redir_test.sh | xargs echo
STDOUT is attached to a pipe
:$ rm bash_redir_test.log
:$ ./bash_redir_test.sh >> bash_redir_test.log
:$ tail bash_redir_test.log
STDOUT is attached to a redirection
在Solaris:
:# ./bash_redir_test.sh
STDOUT is attached to TTY
:# ./bash_redir_test.sh | xargs echo
STDOUT is attached to a redirection
:# rm bash_redir_test.log
bash_redir_test.log: No such file or directory
:# ./bash_redir_test.sh >> bash_redir_test.log
:# tail bash_redir_test.log
STDOUT is attached to a redirection
:#