1

I know this question has been asked several times but it seems ineffective in my case.

[[ ! -t 0 ]] = Does standard input contains anything?

This command:

echo 'Hello world' | [[ ! -t 0 ]]
echo $?

gives the correct output: 0, i.e. the standard input contains anything.
This command:

[[ ! -t 0 ]]
echo $?

gives the correct output: 1, i.e. the standard input is empty.
Instead this command:

: | [[ ! -t 0 ]]
echo $?

gives unexpected output: 0, when instead the standard input is empty: 1.

Why does it behave this way and how can I solve the problem?

Mario Palumbo
  • 233
  • 1
  • 14

1 Answers1

3

[[ ! -t 0 ]] = Does standard input contains anything?

Your premise is wrong. This tests whether stdin is connected to a terminal/tty, not whether stdin contains anything. Because of the negation the command returns 0 (true) if stdin is not connected to a terminal.

See man test:

-t FD file descriptor FD is opened on a terminal

and man bash:

-t fd True if file descriptor fd is open and refers to a terminal.

With this in mind, re-evaluate your examples and you'll see they do indeed return the expected exit status.

The correct way to check if there's anything pending on stdin would be to use select(2), but that's not directly available in a shell such as bash. The closest I can suggest is to use read with an immediate timeout:

sleep 2
if read -t 0 _
then
    echo "Ready to receive data"
    IFS= read -r data
    echo "Received: $data"
fi

Run this, and then during the initial sleep, (a) try preloading stdin with some text, (b) do nothing.

Note that this will still hang (on the read -t 0 _) if you're reading from a pipe and there is no writer present. It will work as I've described if there is a writer present, even if that writer has not written anything to read.

Chris Davies
  • 116,213
  • 16
  • 160
  • 287