|Difference between `exec n<&0 < file` and `exec n|
- The difference should be nothing in modern shells (both should be POSIX compatible), with some caveats:
- There are likely thousands of unique shell binaries in use, some of
which are missing common features or simply buggy.
- Only the first version will behave as expected in an interactive shell,
since the shell will close as soon as standard input gets EOF, which will
happen once it finishes reading
while loop reads from FD 0 in both cases, making the
exec pointless if the shell supports
while loops. To read from FD 9 you have to use
done <&9 (POSIX) or
read -u 9 (in
exec (in this case, see
exec) applies the redirections following it to the current shell, and they
are applied left-to-right. For example,
exec 9<&0 <
file points FD 9 to where FD 0 (standard input) is currently
pointing, effectively making FD 9 a "copy" of FD 0. After that
file is sent to standard input (both FD 0 and 9).
Run a shell within a shell to see the difference between the two
(commented to explain):
$ echo foo > file
$ exec "$SHELL"
$ exec 9<&0 < file
$ foo # The contents of the file is executed in the shell
bash: foo: command not found
$ exit # Because the end of file, equivalent to pressing Ctrl-d
$ exec "$SHELL"
$ exec 9< file # Nothing happens, simply sends file to FD 9
- This is a common misconception about *nix shells: Variables
declared in subshells (such as created by
while) are not
available to the parent shell. This is by design, not a bug. Many
other answers here and on USE
refer to this.