问题
I'm a bit confused as to why when I'm redirecting the standard output of an echo command to the standard error, why I still get the argument printed in the terminal?
Here's is the line I ran
echo "potato" >&2
Could someone explain this to me? How does this command output anything, if the output was redirected somewhere else?
Thank you :)
回答1:
I think what you want is:
bash-3.2$ echo "potato" &>2
bash-3.2$
From the man
page for bash:
Redirecting Standard Output and Standard Error
Bash allows both the standard output (file descriptor 1) and
the standard error output (file descriptor 2) to be redirected to the file
whose name is the expansion of word with this construct.
There are two formats for redirecting standard output and standard error:
&>word
and
>&word
Of the two forms, the first is preferred. This is semantically equivalent to
>word 2>&1
回答2:
At first, when your terminal and shell starts, both STDOUT and STDERR points to the terminal output. Your command echo "potato" >&2
is asking to redirect STDOUT to what STDERR points to. Thus this command has no effect at all.
Here's some references:
- File descriptor 0 (FD0) is named STDIN
- File descriptor 1 (FD1) is named STDOUT
- File descriptor 2 (FD2) is named STDERR
- File descriptor 3 (FD3) and more has no special names.
- Any unix program initially has all those 3 file descriptors opened by default.
- STDIN by default points to the input device (of the terminal opening the program), normally finally to keyboard
- STDOUT, STDERR by default point to the console (terminal) output
> somefile
or1> somefile
redirects file descriptor 1 to the file named 'somefile', i.e. pointing STDOUT to 'somefile'n> somefile
redirects file descriptor n to the file named 'somefile', wheren
= 1, 2, 3, ...n
by default is 1, whenn
is omitted.n>&m
redirects file descriptor n to file descriptor m.- When we say file descriptor n is redirected to file descriptor m, we actually mean that file descriptor n is forced to point to what file descriptor m pointing to, for example, the terminal output device/console.
n>&-
closes file descriptor n, where n = 1, 2, 3, ...- The order of the redirections are important. They are applied from left to right. See example below:
# FD1 (file descriptor1, i.e. STDOUT) is redirected (pointing) to the file named 'file.log`
# Then FD2 is pointing to what FD1 points to, i.e. 'file.log'. Thus the following command
# redirection both "potato" and the error output of 'ls xx' to file.log:
$ (echo "potato"; ls xx) > file.log 2>&1
$ cat file.log
potato
ls: cannot access xx: No such file or directory
# FD2 is redirected (pointing) to what FD1 points to, i.e. the terminal output. (This has no effect, since FD2 was pointed to the terminal anyway.
# FD1 is then redirected to file.log
# Thus the following command only redirects "potato" to file.log, and left the error message
# displayed on the terminal.
$ (echo "potato"; ls xx) 2>&1 > file.log
ls: cannot access xx: No such file or directory
$ cat file.log
potato
- Ordering between redirection and pipe (Pipe first, and then the redirections). So, this command:
command1 > /dev/null | comamnd2
first create pipe between command1, and command2, i.e. link STDOUT of command 1 to STDIN of command2. Then, STDOUT of command1 is redirected to /dev/null. This essentially cancels the pipe (disengages the pipe). Thus command2 will sees end of the STDIN input, i.e. STDIN of command2 is closed.
So, it explains why the following command exchanges STDIN and STDOUT:
$ (echo xx; ls xx) 3>&1 1>&2 2>&3 3>&- | wc -l
ls: cannot access xx: No such file or directory
1
- Step1: pipe is created, FD1 (left side) points to pipe-out. FD0 of
wc
points to pipe-in - Step2: FD3 is created, duplicating FD1, i.e. pointing to pipe-out
- Step3: FD1 is now changed to what FD2 pointing to, i.e. the terminal output.
- Step4: FD2 is now changed to what FD3 pointing to, i.e. the pipe-out.
- Step5: FD3 is closed.
The net effects are:
FD1 now points to the terminal output.
FD2 now points to the pipe-out, piping outputs to wc
command.
Hope this helps.
回答3:
Well, by default, your terminal shows both STDOUT and STDERR.
So, what you are seeing is STDERR.
If you want to hide STDERR: echo "potato" 2>/dev/null >&2
/dev/null
is a black-hole, where you can redirect stuff you have no wish to see :)
回答4:
Because standard error is also displayed in terminal by default. So you redirect your standard output to standard error which in turn gets redirected to the console. The result does not change.
回答5:
The output is simply going where it's told to go
By default file descriptor 1 and 2 point to the same location (note >&2
is equivalent to 1>&2
)
> $ ls -l /proc/$$/fd/
total 0
lrwx------ 1 foo foo 64 Dec 23 18:42 0 -> /dev/pts/3
lrwx------ 1 foo foo 64 Dec 23 18:42 1 -> /dev/pts/3
lrwx------ 1 foo foo 64 Dec 23 18:42 2 -> /dev/pts/3
And now let's say we redirect one of those file descriptors to point elsewhere
> exec 1>foo
> ls -l /proc/$$/fd/
> exec 1>&2
> cat foo
total 0
lrwx------ 1 foo foo 64 Dec 23 18:42 0 -> /dev/pts/3
lrwx------ 1 foo foo 64 Dec 23 18:42 1 -> /home/foo/foo
lrwx------ 1 foo foo 64 Dec 23 18:42 2 -> /dev/pts/3
Note the output of ls -l /proc/$$/fd/
went to file foo
in our working directory rather than being printed to stdout.
来源:https://stackoverflow.com/questions/27630177/redirection-of-echos-standard-output-to-standard-error-still-produces-output-i