If there is nothing in a named pipe and I do:

cat my_named_pipe

it will wait until data arrives. Is there a flag I can use to exit immediately if there is no data to be read? Or perhaps a command other than cat that I can use?

I also tried:

read val < "$my_named_pipe";

but this also waits for the next chunk of data - I don't want to wait if the fifo is empty.

  • Hmmm... Unfortunately, read in bash with a timeout (its -t option) doesn't seem to cut it.
    – Kusalananda
    Jun 4, 2019 at 17:36
  • @Kusalananda, it's the open() (the redirection), not the read() that blocks when there's no writer to the pipe. Jun 4, 2019 at 17:37
  • @StéphaneChazelas Ah, yes, that makes sense.
    – Kusalananda
    Jun 4, 2019 at 17:37

2 Answers 2


To prevent cat from hanging in the absence of any writer (in which case it's the opening of the fifo, not reading from it, that hangs), you can do:

cat 0<> "$my_named_pipe" <"$my_named_pipe"

The first redirection opens in read+write mode which on most systems doesn't block and instantiates the pipe even if there's no writer nor reader already. Then the second open (read-only this time) would not block because there is at least one writer now (itself).

The 0 is only needed in recent versions of ksh93 where the default fd for <> changed from 0 to 1.

Also, in ksh93, that would not work when cat is the shell builtin, like when ksh93 is called when /opt/ast/bin is ahead of /bin in $PATH or after a call to builtin cat as upon the <"$my_named_pipe", (I guess) ksh93 saves the previous target of stdin on a separate file descriptor which would hold the pipe open. You can work around that by writing it instead:

cat 3<> "$my_named_pipe" <"$my_named_pipe" 3<&-

(which you might also argue conveys the intention more clearly)

Note that that <> on the pipe would also unlock other readers to the fifo.

If there were some writers, cat would still have to read all their output and wait until they have closed their end of the pipe. You could open the pipe in non-blocking mode, like with GNU dd's:

dd bs=64k if="$my_named_pipe" iflag=nonblock status=noxfer

Which would only read from the pipe as long as there's some data in it, and exit with a

dd: error reading 'fifo': Resource temporarily unavailable

error when there's no more, and not unlock other readers, but that means you could miss some of the writers output if they are slower to write to the pipe than you (dd) are to read it.

Another approach could be to timeout when there's been no input in a while, for instance by using socat's -T option:

socat -u -T1 - - 0<> "$my_named_pipe" <"$my_named_pipe"

Which would exit if there's not been anything coming from the pipe in one second.

  • seems to work, but I have no idea why - the named pipe should pre-exist, so I don't need to instantiate it? Jun 4, 2019 at 17:46
  • 2
    nb: that trick still relies on all the other writers to close the pipe in order for the cat to return. If another process has opened the pipe with eg. exec 7>fifo and keeps the fd 7 open, the cat <>fifo <fifo will still block, but not when trying to open the pipe, but when trying to read more data from it.
    – user313992
    Jun 4, 2019 at 18:11
  • @mosvy, thanks. See edit where I've added more notes and details. Jun 5, 2019 at 5:16

Something quite easy would be to terminate cat immediately after reading the fifo, irrespective of whether there is data or not. You could do this with timeout, as follows:

timeout 2 cat my_named_pipe

Above, timeout waits for two seconds before forcing cat to terminate. If there is something buffered in the named pipe when you run cat, it will be printed to stdout.

Maybe not the cleanest solution but does the job.

Hope it helps.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .