It’s a bit difficult but doable:
function die {
print -ru2 -- "E: $*"
exit 1
}
function psubin {
local stdin=$(cat; echo .) pipe
pipe=$(mktemp /tmp/psub.XXXXXXXXXX) || die mktemp
# this is racy
rm -f "$pipe"
mkfifo "$pipe" || die mkfifo
(
# don’t block parent
exec <&- >&- 2>&-
# write content to FIFO
print -nr -- "${stdin%.}" >"$pipe"
# signal EOF to reader, ensure it’s not merged
sleep 0.1
:>"$pipe"
# clean up
(sleep 1; rm -f "$pipe") &
) &
print -nr -- "$pipe"
}
diff -u $(echo abc | psubin) $(echo def | psubin)
The problems you and I encountered here are:
mkfifo
complains unless you rm
mktemp
’s output first
- mksh blocks for the background process if it still shares any file descriptors (stdin, stdout, stderr) with the parent (Note: This is probably the only valid use case for using
>&-
instead of >/dev/null
, and only because we can guarantee these fds to no longer be used, nor replaced by any new fds)
- as we don’t have stdin in the background process we’ll need to cache its content, byte-exact
- EOF with FIFOs (named pipes) is nontrivial. Let’s just leave at that… (we could do some tricks with trying to open the FIFO non-blocking to check if there’s a reader, and signal EOF until the reader died, but this works well enough for now)
- it’s nicer if the FIFO is removed after use…
On the other hand: good thing we’re doing this now, because I eventually will wish to implement <(…)
into mksh itself, and then I need to know what to watch out for, since we can’t use /dev/fd/
as GNU bash does, because that’s not portable enough.
diff <(echo abc) <(echo def )
in bash ? (and fish example is not working for me) – Archemar Mar 29 '16 at 11:59$(…)
is POSIX and, in fact, highly recommended over the older form that used an accent gravis for substitution, as it defines a full recursive shell and quoting environment. – mirabilos Mar 30 '16 at 19:03cmd >$(log_it ..) 2>$(log it ...)
. But, it doesn't seem to work for my example w/diff
:diff $( proc | proc ) $( proc | proc)
. Thediff
won't run until the subshells exit. In my case, diff needs the output of the subshells. But, I also need to cleanup named pipes. The problem is the subshells need to exit, preventing the cleanup of the named pipes. – dgo.a Mar 30 '16 at 19:24abc
from the FIFO, then wants to read more from it. At this time, it should be signalled EOF but isn’t. I’m currently investigating why. -- mksh author here – mirabilos Mar 30 '16 at 19:28