It means, if I understand correctly, that all commands trying to read from stdin will actually read from file
A command reading from its stdin will read from a regular file if its stdin happens to be the regular file. A command reading from its stdin will read from a terminal or from a fifo (which are also files) if its stdin happens to be the terminal the fifo respectively.
Stdin of one command can be different than stdin of another command.
In a script interpreted by bash
, exec < file
redirects the stdin of this particular bash
process only. Later commands will be affected if they inherit stdin, but the inheritance happens in the same way regardless if you used exec < file
or not.
If you run just cmd0
then it will inherit stdin and stdout (and stderr) from the interpreting bash
. It's irrelevant what the stdin and stdout of the interpreting bash
are; the mechanism is always the same.
If you run cmd1 | cmd2 | … | cmdN
then cmd1
will inherit stdin from the interpreting bash
and cmdN
will inherit stdout from the interpreting bash
. Other stdins and stdouts will form a pipeline (stdout of cmd1
connected to stdin of cmd2
and so on). It's irrelevant what the stdin and stdout of the interpreting bash
are; the mechanism is always the same.
The fact you used exec < file
is irrelevant to the mechanism itself. Some command(s) will inherit stdin and/or stdout from the interpreting bash
. Without exec < file
they would inherit something. With exec < file
they will inherit something else as stdin.
This means exec < file
can affect some commands, but only commands that inherit stdin from the interpreting bash
. Your cmd1
does inherit the stdin of the interpreting bash
, but cmd2
does not.
Assuming your cmd2
simply reads from its stdin, it will read from the output of cmd1
. The prior exec < file
doesn't matter. (Note in general cmd2
may redirect or ignore or close its stdin; commands designed to work in pipelines don't do this, unless told to.)
You can test this in a script:
#!/bin/bash# Don't run this in an interactive shell. Run as a script.exec < /etc/fstabecho foo | catwc -l
Note if you paste the above code in an interactive bash
then you will change the stdin of the bash
itself and it will eventually exit upon EOF. For your convenience below is a version that can be run in an interactive shell without terminating it:
bash -c ' exec < /etc/fstab echo foo | cat wc -l'
The output should be foo
(proving cat
reads the output of echo
) followed by a number being the number of lines in your fstab
(proving wc
reads from fstab
).