I am trying to echo outputs to stderr and redirect stderr to a file at the same time, I noticed that the order of redirection matters, but I don't understand why it has to be this way.
The file asap
is empty using either of the following commands:
echo "Fatal error." >&2 2>asap
echo >&2 "Fatal error." 2>asap
But this works, logging "Fatal error" to the file asap
.
echo "Fatal error." 2>asap >&2
Why?
See How to pipe stderr and not stdout for most of the required information. Note the 'au contraire' comment, in particular. Remember that all redirections are completed before the command is executed, and that the redirections are processed from left to right. (Pipelines marginally complicate the story. Most of the time, the pipe redirection of standard output is done before any other redirection. The exception is a Bash-specific syntax, |&
. Go read the Bash manual for the details — and then don't use |&
.)
Note that the redirections can be positioned anywhere on the command line relative to the command name and arguments. That is:
<html> xml some -command
is the same as
some -command <html >xml
and so on. So, there is no difference between the first two commands in the question. (And I think you found that out for yourself.)
The first command in the question:
echo "Fatal error." >&2 2>asap
first redirects standard output to the current standard error, then redirects standard error to the file (leaving standard output pointing to the original standard error), and then executes the echo
command. The message goes to the original standard error (your terminal), and not to the file because echo
doesn't write to standard error.
The last command:
echo "Fatal error." 2>asap >&2
first sends standard error to the file, then sends standard output to the same place that standard error is going to (the file), and then executes the echo
command. Since standard output is going to the file, there's nothing seen on the terminal.