In bash you can do:
echo test >&1
(redirect to stdout, although it's already going there)echo test >&2
(redirect to stderr)echo test >&0
(redirect to stdin)When I do the last one my terminal still prints test
as it would with the other two, but it's hard to know why. So first off, why does this work at all? Secondly, are there any good uses for redirecting to stdin?
There can be used in a couple of ways. As an adverb, there is the exact opposite of the word here and means “at that place”: He asked me to go there and check on his fish while he's away. There is also often used as a pronoun.
Their is the possessive pronoun, as in "their car is red"; there is used as an adjective, "he is always there for me," a noun, "get away from there," and, chiefly, an adverb, "stop right there"; they're is a contraction of "they are," as in "they're getting married."
To be more precise, what >&0
does is duplicate file descriptor 0 as file descriptor 1. If the program's stdin is only open for reading, then when your program tries to write to stdout (file descriptor 1), it will get an error because file descriptor 1 is also only open for reading.
You can demonstrate this by writing a small shell script that inspects its own file descriptors:
10156115.sh:
#!/bin/bash
bash -c 'ls -l /proc/$$/fd' >&0
And then invoke it with identifiable stdin, stdout and stderr:
$ touch stdin
$ ./10156115.sh < stdin > stdout 2> stderr
The result is that you get the following in stderr
:
ls: write error: Bad file descriptor
However, by default, all three are a terminal: (output simplified)
$ ls -l /proc/$$/fd
lrwx------ 0 -> /dev/pts/14
lrwx------ 1 -> /dev/pts/14
lrwx------ 2 -> /dev/pts/14
lrwx------ 255 -> /dev/pts/14
Typically, all three are actually open read+write, so the >&0
redirect has no effect at all if used alone from a normal shell.
Are there any uses for this?
There aren't any common uses of this, but you might use it as a dirty hack to get a way to print to the terminal if whomever calls your script redirects stdout
and stderr
, and for whatever reason you're not able to change that:
if [ ! -t /dev/fd/1 -a ! -t /dev/fd/2 -a -t /dev/fd/0 ]; then
echo "My message that I really, really want to go to a terminal" >&0
fi
But I wouldn't recommend actually doing this.
For historical reasons, the standard file descriptors on a terminal are open read/write instead of read-only (specifically, it's opened once and dup()
ed to the others). This is occasionally useful for programs that want to take piped input but also read input from the user (from stdout
, or more commonly stderr
), although using /dev/tty
is more reliable in that case. Some systems apply this to more than just ttys: the *BSDs open socketpairs ("pipes") bidirectionally, and some system utilities (I recall ufsdump
being an example) depend on this.
Redirecting to stdin
(that is, having it open only for write) is not generally useful, since most programs expect it to be open for read (or sometimes read/write, as above).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With