How to check if a pipe is empty and run a command on the data if it isn't?
There's no way to peek at the content of a pipe using commonly available shell utilities, nor is there a way to read a character from the pipe then put it back. The only way to know that a pipe has data is to read a byte, and then you have to get that byte to its destination.
So do just that: read one byte; if you detect an end of file, then do what you want to do when the input is empty; if you do read a byte then fork what you want to do when the input is not empty, pipe that byte into it, and pipe the rest of the data.
first_byte=$(dd bs=1 count=1 2>/dev/null | od -t o1 -A n | tr -dc 0-9)
if [ -z "$first_byte" ]; then
# stuff to do if the input is empty
else
{
printf "\\$first_byte"
cat
} | {
# stuff to do if the input is not empty
}
fi
The ifne
utility from Joey Hess's moreutils runs a command if its input is not empty. It usually isn't installed by default, but it should be available or easy to build on most unix variants. If the input is empty, ifne
does nothing and returns the status 0, which cannot be distinguished from the command running successfully. If you want to do something if the input is empty, you need to arrange for the command not to return 0, which can be done by having the success case return a distinguishable error status:
ifne sh -c 'do_stuff_with_input && exit 255'
case $? in
0) echo empty;;
255) echo success;;
*) echo failure;;
esac
test -t 0
has nothing to do with this; it tests whether standard input is a terminal. It doesn't say anything one way or the other as to whether any input is available.
A simple solution is to use ifne
command (if input not empty). In some distributions, it is not installed by default. It is a part of the package moreutils
in most distros.
ifne
runs a given command if and only if the standard input is not empty
Note that if the standard input is not empty, it is passed through ifne
to the given command
check if file descriptor of stdin (0) is open or closed:
[ ! -t 0 ] && echo "stdin has data" || echo "stdin is empty"