On Fri, Jul 05, 2024 at 04:10:55PM -0400, Dale R. Worley wrote: > Emanuele Torre <torreemanue...@gmail.com> writes: > > Bash 5.2 apparently added <(< file) that expand to the path to a fifo > > (openable only for read on BSD) to which the contents of file are > > written to, without documenting it. > > I suspect that this is a consequence of > > The com‐ > mand substitution $(cat file) can be replaced by the equivalent but > faster $(< file). >
Yes, clearly that is influencing this new behaviour, but this is new: <(<file) >(<file) did not have that special behaviour previously. The <(<file) behaviour is neat, so it would be nice if at least that one was documented. > (Which oddly enough, I suggested for Bash some decades ago.) In the > latter form, Bash doesn't set up a subprocess and then read the pipe > from it but instead just reads the named file. Or rather, that was the > initial implementation. I suspect that the code has been updated so > that an "inner command" of "< file" now copies "file" to stdout (as if > it was cat), and the various results you see are based on what the > parent process does with that output. More funny things have been discovered since. It has been brought up when discussing this in the #bash IRC channel of irc.libera.chat, that if you run eval '<file' in $(), the contents of file are output to stdout, in every version of bash since it was introduced. So you can for example use this to concatenate two files in pure bash; like $(cat <f; cat <g): bash-5.2$ echo hi > f bash-5.2$ echo ih > g bash-5.2$ x=$(eval '<f'; eval '<g') bash-5.2$ declare -p x declare -- x=$'hi\nih' And indeed to output a file to stdout in pure bash, in any version of bash that has $(<): bash-5.2$ printf hi\\nhello > file bash-5.2$ { _=$(eval '< file' >&3) ;} 3<&1 hi hellobash-5.2$ I have also noticed that if you source a file from $() and the last logical line of that file contains only a simple command with only one read-only stdin redirection, bash will also print out that file, again, in all versions of bash with $(<): bash-5.2$ printf hello > myfile bash-5.2$ cat <<'EOF' > tosource echo foo < myfile EOF bash-5.2$ x=$(. ./tosource; echo hey) bash-5.2$ declare -p x declare -- x=$'foo\nhellohey' > > Dale o/ emanuele6