2>&1
is one redirection - send fd2 into fd1, effectively sending stderr into stdout.
The second bit, /dev/null
doesn't do any redirection. You probable meant to redirect stdout to /dev/null, so it should be > /dev/null
, but as davidxxx mentioned, it should be the other way around (not especially intuitive, imo).
If you just want to redirect one, then just do that:
$ (echo stdout; ls /dev/error) 1>/dev/null
ls: /dev/error: No such file or directory
$ (echo stdout; ls /dev/error) 2>/dev/null
stdout
$
and, of course, you can do both individually (order doesn't matter since it's /dev/null - I guess it would for a regular file?):
$ (echo stdout; ls /dev/error) 2>/dev/null 1>/dev/null
$
You can send stderr(2) into fd1 so it is 'merged' with stuff written to stdout - it looks the same as if you did nothing:
$ (echo stdout; ls /dev/error) 2>&1
stdout
ls: /dev/error: No such file or directory
but if you put it in a subshell and redirect the resulting stderr(2) to /dev/null, you can see that it is actually part of stdout(1) because nothing changes:
$ ((echo stdout; ls /dev/error) 2>&1) 2>/dev/null
stdout
ls: /dev/error: No such file or directory
as opposed to:
$ ((echo stdout; ls /dev/error) ) 2>/dev/null
stdout
So, yeah, you wanted:
$ (echo stdout; ls /dev/error) >/dev/null 2>&1
which is the same as:
$ (echo stdout; ls /dev/error) 1>/dev/null 2>&1
and, indeed has the same effect as (open /dev/null as fd[2], fd[1] = fd[1]):
$ (echo stdout; ls /dev/error) 2>/dev/null 1>&2
Maybe a good tip is to think of the low level system calls - I think it might help make the order make sense.
2>/dev/null
- open /dev/null with file descriptor 2.
1>&2
- instead of writing to fd 1, write to fd 2 (which has been opened on /dev/null). You could imagine it internally doing fd[2] = fd[1];
.
Of course, if you don't care about the output, then perhaps you should consider closing them both:
$ (echo stdout; ls /dev/error) 1>&- 2>&-
$
This could cause problems if you don't close stderr(2) since zsh/echo will try to write to stdout(1), which is closed:
$ (echo stdout; ls /dev/error) 1>&-
zsh: write error: bad file descriptor
ls: /dev/error: No such file or directory
but it's an option to consider. Works nicely for stderr, it seems (nowhere to complain to).
zsh: no matches found:
-- that's notls: no matches found
; the error is being written by the shell beforels
starts (as it's the shell responsible for replacing paths with wildcards with things that actually exist on the filesystem); so it's unsurprising that redirectingls
's stderr has no effect. – Intrude