Detect if stdout is redirected to a pipe (not to a file, character device, terminal, or socket)?

孤者浪人 提交于 2019-12-03 13:24:34

(my comment turned to answer per Alex Dupuy's suggestion) Since you said you can use perl, I guess you can use its -p file test operator (perldoc.perl.org/functions/-X.html); something like perl -e 'exit(-p STDOUT ? 0 : 1);' will tell you if stdout if a pipe or a fifo (without distinguishing between them).

Fwiw, calling that from the shell is exactly the reason why I used perl -e :)

You could do an fstat to the file descriptor and check returning structure, for example, st_mode = 0x1000 (S_IFIFO) indicates a Named Pipe.

Example with Python:

from __future__ import print_function
import sys
import os

print(os.fstat(sys.stdout.fileno()), file=sys.stderr)

Output on windows:

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)

The stat command works on MacOS X and (with some finessing of variant implementations) other Linux/Unix variants as well, so it is a solution for me:

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

In Python:

import sys
print sys.stdout.isatty()

Examples:

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

There is a Linux-specific solution that does what I want:

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

but that isn't the answer I am looking for as I want this to run on xBSD as well.

I've made this answer community wiki, so feel free to improve it, but if you have a non-Linux solution (or a Linux-specific solution using another technique), please create a new answer.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!