How to check if stdin is /dev/null from the shell?

On linux, you can do it with:

stdin_is_dev_null(){ test "`stat -Lc %t:%T /dev/stdin`" = "`stat -Lc %t:%T /dev/null`"; }

On a linux without stat(1) (eg. the busybox on your router):

stdin_is_dev_null(){ ls -Ll /proc/self/fd/0 | grep -q ' 1,  *3 '; }

On *bsd:

stdin_is_dev_null(){ test "`stat -f %Z`" = "`stat -Lf %Z /dev/null`"; }

On systems like *bsd and solaris, /dev/stdin, /dev/fd/0 and /proc/PID/fd/0 are not "magical" symlinks as on linux, but character devices which will switch to the real file when opened. A stat(2) on their path will return something different than a fstat(2) on the opened file descriptor.

This means that the linux example will not work there, even with GNU coreutils installed. If the versions of GNU stat(1) is recent enough, you can use the - argument to let it do a fstat(2) on the file descriptor 0, just like the stat(1) from *bsd:

stdin_is_dev_null(){ test "`stat -Lc %t:%T -`" = "`stat -Lc %t:%T /dev/null`"; }

It's also very easy to do the check portably in any language which offers an interface to fstat(2), eg. in perl:

stdin_is_dev_null(){ perl -e 'exit((stat STDIN)[6]!=(stat "/dev/null")[6])'; }

On Linux, to determine whether standard input is redirected from /dev/null, you can check whether /proc/self/fd/0 has the same device and inode as /dev/null:

if [ /proc/self/fd/0 -ef /dev/null ]; then echo yes; else echo no; fi

You can use /dev/stdin instead of /proc/self/fd/0.

If you want to check whether standard input is redirected from the null device, you need to compare major and minor device numbers, for example using stat (see also mosvy’s answer):

if [ "$(stat -Lc %t:%T /dev/stdin)" = "$(stat -Lc %t:%T /dev/null)" ]; then echo yes; else echo no; fi

or, if you don’t care about this being Linux-specific,

if [ "$(stat -Lc %t:%T /dev/stdin)" = "1:3" ]; then echo yes; else echo no; fi

Portably, to check that stdin is the null device (open on /dev/null or not (like a copy of /dev/null)), with zsh (whose stat builtin predates both GNU and FreeBSD stat by the way (not IRIX' though))):

zmodload zsh/stat
if [ "$(stat +rdev -f 0)" = "$(stat +rdev /dev/null)" ]; then
  echo stdin is open on the null device
fi

(note that it doesn't say if the file descriptor was open in read-only, write-only or read+write mode).

To check that it's open on the current /dev/null file specifically (not /some/chroot/dev/null for instance), on Linux only (where /dev/stdin is implemented as a symlink to the file open on fd 0 instead of a special device which when open acts like a dup(0) in other systems):

if [ /dev/stdin -ef /dev/null ]; then
  echo stdin is open on /dev/null
fi

On non-Linux, you can try:

if sh -c 'lsof -tad0 -p"$$" /dev/null' > /dev/null 2>&-; then
  echo stdin is open on /dev/null
fi