[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: redirection / process substitution fails to read a file descriptor
From: |
Greg Wooledge |
Subject: |
Re: redirection / process substitution fails to read a file descriptor |
Date: |
Sat, 16 Nov 2024 21:35:43 -0500 |
On Sat, Nov 16, 2024 at 16:35:05 -0600, Mike Peters wrote:
> Description:
> Process substitution does not generate properly when pulling from
> another file descriptor, although it works when pulling from a file directly.
> In the below sample shell session, it is expected that `<(<test.txt)` would
> be functionally equivalent to `<(<&3)`.
> Repeat-By:
> > echo foobar > test.txt
> > echo `< <(<test.txt)`
> foobar
This is one of the most convoluted things I've seen in a long time.
You've got a command substitution with < as its command, which is
equivalent to $(cat ...) as a bash extension. The argument of </cat
is a process substitution with a *second* instance of < being used
as a command.
So, going from the innermost layer outward, you have a process
substitution which reads a file's contents and dumps it to the
procsub's FD (the way cat would), and this FD is being treated as
a filename by a command substitution's </cat which in turn dumps
the data to the commsub's internal pipe. The commsub read the
content from the procsub FD and is replaced by that content, which
happens to be the string "foobar". This is passed as an argument
to echo.
> > exec 3<test.txt
> > cat <&3
> foobar
OK. This part is straightforward. Note that you used a command, cat,
to write output. You didn't simply type <&3 without a command.
> > exec 3<test.txt
> > echo `< <(<&3)`
>
> >
Here, you've got a process substitution with <&3 inside it. I can
only guess what this is going to do. It doesn't follow the standard
form of < filename which would be treated like cat filename, even though
it begins with a < character.
I'm guessing that the parser sees the <& and decides *not* to treat
this as a shortcut of cat with &3 as a filename. Therefore, the only
thing the parser can do is treat this as an empty command with a <&3
redirection attached to it.
So, your process runs an empty command with a stdin redirection,
which produces no output. The procsub therefore receives no data.
So the filename that the procsub is replaced by may as well be a symlink
to /dev/null.
Then, you have the command substitution with < followed by that
filename, which contains no data. The commsub produces no output,
so it's replaced by nothing. (The commsub is not quoted, so it
simply vanishes, leaving echo with no arguments.)
echo is executed with no arguments, so it writes a newline to stdout.
If you expected the inner process substitution to generate output,
then there needs to be a command of some kind inside it, and that
command should write to stdout. The obvious pick would be cat.
In the *first* segment of code, your inner process substitution had
the < command inside it, which acts like cat, because of a bash
extension. You're missing that in the final code segment.