如何检测标准输出是否被redirect到pipe道(而不是文件,字符设备,terminal或套接字)?

理想情况下,这可以在shell中编写脚本,但是Perl或者Python也可以。 C代码可能会有帮助,但可能会失败成本/收益。

我认识到,redirect到一个FIFO(命名pipe道)可能是无法区分的真正的pipe道,这是足够的边缘情况下,我真的不在乎。

严格的POSIX解决scheme是最好的,UNIX / Linux变体独立是次佳,但至less在达尔文(MacOS X)上工作的东西是我现在需要的。

在你写答案之前 – 我已经知道test -t – 它会告诉我stdout是否是一个terminal(在这种情况下,它绝对不是一个pipe道 – 但它不会告诉我stdout是否已被redirect到一个文件, – terminal字符设备,或UNIX域套接字而不是pipe道。

预期用例:我有一个应该在shell中的反引号内运行的命令,以便它可以输出设置环境variables的命令。 如果stdout没有被redirect到一个pipe道,我想这个命令会中止一个错误,因为在这种情况下,它肯定不会被eval `mycommand`;调用eval `mycommand`;

如果在反引号内运行一个命令时shell会设置一些特殊的环境variables会很有帮助,但是由于它可能是bash或zsh之类的东西,所以pipe道检测更重要。

(我的评论转向按Alex Dupuy的建议回答)既然你说过你可以使用perl,我想你可以使用它的-p文件测试运算符( perldoc.perl.org/functions/-X.html ); 像perl -e 'exit(-p STDOUT ? 0 : 1);' 会告诉你,如果标准输出管道或先锋( 没有区分他们)。

Fwiw,从shell调用正是我使用perl -e的原因:)

您可以对fstat执行fstat并检查返回的结构,例如, st_mode = 0x1000(S_IFIFO)表示命名管道。

Python的例子:

 from __future__ import print_function import sys import os print(os.fstat(sys.stdout.fileno()), file=sys.stderr) 

在窗口输出:

 C:> python test_fd.py | more nt.stat_result(st_mode=4096, st_ino=0L, st_dev=0, st_nlink=0, st_uid=0, st_gid=0, st_size=0L, st_atime=0L, st_mtime=0L, st_ctime=0L) C:> python test_fd.py > test_fd.txt nt.stat_result(st_mode=33206, st_ino=16888498602769633L, st_dev=0, st_nlink=1, st_uid=0, st_gid=0, st_size=0L, st_atime= 1401119520L, st_mtime=1401119520L, st_ctime=1401119349L) 

stat命令适用于MacOS X以及其他Linux / Unix版本的变体实现,所以对我来说这是一个解决方案:

 FORMOPT= TYPEFORM= stat() { if [ -z "$FORMOPT" ]; then if /usr/bin/stat --version >/dev/null 2>&1; then FORMOPT=--format TYPEFORM=%F else FORMOPT=-f TYPEFORM=%HT fi fi case $1 in type) FORMARG="$FORMOPT $TYPEFORM" ; shift ;; esac /usr/bin/stat -L $FORMARG "$@" } exec 9>&1 case `stat type /dev/fd/9` in [Ff]ifo*) echo stdout is a pipe ;; *) echo stdout is not a pipe ;; esac 

有一个Linux特定的解决方案,做我想要的:

 exec 9>&1 case `readlink /dev/fd/9` in pipe:\[*\]) echo stdout is a pipe ;; *) echo stdout is not a pipe ;; esac 

但这不是我正在寻找的答案,因为我希望这个在xBSD上运行。

我已经做了这个答案社区wiki,所以随时可以改进它,但如果你有一个非Linux的解决方案(或使用其他技术的Linux特定的解决方案),请创建一个新的答案。

在Python中:

 import sys print sys.stdout.isatty() 

例子:

 $ ./a True $ ./a | less False