danger/u/
cat stdin into a fifo

| Here's a shell snippet:

if [ $# -ge 1 ]
then printf '%s\n' "$@"
else cat
fi | while IFS= read -r arg
do
something -cool -with "$arg"
done

Works like charm. You can have positional arguments or pipe into stdin.

Now I want the while loop to run in the current environment instead of a subshell. I try:

mkfifo fifo
if [ $# -ge 1 ]
then printf '%s\n' "$@"
else cat
fi >fifo
while IFS= read -r arg
do
something -cool -with "$arg"
done <fifo


| doesn't. Why doesn't it work?

Even just

cat >fifo &

doesn't work (I missed a & in the example. It's not the reason)


| Positional args do work though


| Because bash has syntax designed by clinicaly insane


| This is not a syntax issue


| It always is


| The fact that the while loop does not block means it isn't


| this won't work because the writer blocks waiting for a reader, this is why the subshell approach works (reader is immediately accessible)
use process substitution if you must continue on this path, file descriptors are safer than pipes
otherwise stop using bash i beg of you


| but I've been using this with jq as in

jq .[] <json >fifo &
while read…

and it worked. Should I not do this?


| >>1097754
>this won't work because the writer blocks waiting for a reader, this is why the subshell approach works (reader is immediately accessible)

that is why I run cat in background

>stop using bash i beg of you

This is not bash it's meant to be POSIX shell. I use dash for /bin/sh


| >>1097754
> this won't work because the writer blocks waiting for a reader, this is why the subshell approach works (reader is immediately accessible)

Why does printf work in that case?


| My logic is if it works with a pipe, it should work with a named pipe.


| is this niggerlicious, or is this divine intellect?


| When we use pipelines stdin of the shell is redirected to the frist pipeline process and stdout is redirected from the last process. When I tried to “do it manually” the automatic redirection did not happen so cat does not read from shell's stdin. The sulution is to duplicate the stdin fd.


| mkfifo fifo
exec 4<&0
if [ $# -ge 1 ]
then printf '%s\n' "$@"
else cat <&4
fi >fifo &
while IFS= read -r arg
do
something -cool -with "$arg"
done <fifo

Now cat reads from fd 4 instead of whatever is fd 0 in the background process (probably /dev/null).

Total number of posts: 15, last modified on: Thu Jan 1 00:00:00 1780051232

Refresh