The numbers are file descriptors and only the first three (starting with zero) have a standardized meaning:
0 - stdin
1 - stdout
2 - stderr
So each of these numbers in your command refer to a file descriptor. You can either redirect a file descriptor to a file with >
or redirect it to another file descriptor with >&
The 3>&1
in your command line will create a new file descriptor and redirect it to 1
which is STDOUT
. Now 1>&2
will redirect the file descriptor 1 to STDERR
and 2>&3
will redirect file descriptor 2 to 3 which is STDOUT
.
So basically you switched STDOUT
and STDERR
, these are the steps:
- Create a new fd 3 and point it to the fd 1
- Redirect file descriptor 1 to file descriptor 2. If we wouldn't have saved the file descriptor in 3 we would lose the target.
- Redirect file descriptor 2 to file descriptor 3. Now file descriptors one and two are switched.
Now if the program prints something to the file descriptor 1, it will be printed to the file descriptor 2 and vice versa.
From http://www.manpagez.com/man/1/ksh/:
<>word Open file word for reading and writing as standard out-
put.
<&digit The standard input is duplicated from file descriptor
digit (see dup(2)). Similarly for the standard output
using >&digit.
<&- The standard input is closed. Similarly for the standard
output using >&-.
You will find all those details by typing man ksh
.
Especially 2>&-
means: close the standard error stream, i.e. the command is no longer able to write to STDERR, which will break the standard which requires it to be writable.
To understand the concept of file descriptors, (if on a Linux system) you may have a look at /proc/*/fd
(and/or /dev/fd/*
):
$ ls -l /proc/self/fd
insgesamt 0
lrwx------ 1 michas users 1 18. Jan 16:52 0 -> /dev/pts/0
lrwx------ 1 michas users 1 18. Jan 16:52 1 -> /dev/pts/0
lrwx------ 1 michas users 1 18. Jan 16:52 2 -> /dev/pts/0
lr-x------ 1 michas users 1 18. Jan 16:52 3 -> /proc/2903/fd
File descriptor 0 (aka STDIN) is used per default for reading, fd 1 (aka STDOUT) is default for writing, and fd 2 (aka STDERR) is default for error messages. (fd 3 is in this case used by ls
to actually read that directory.)
If you redirect stuff it might look like this:
$ ls -l /proc/self/fd 2>/dev/null </dev/zero 99<>/dev/random |cat
insgesamt 0
lr-x------ 1 michas users 1 18. Jan 16:57 0 -> /dev/zero
l-wx------ 1 michas users 1 18. Jan 16:57 1 -> pipe:[28468]
l-wx------ 1 michas users 1 18. Jan 16:57 2 -> /dev/null
lr-x------ 1 michas users 1 18. Jan 16:57 3 -> /proc/3000/fd
lrwx------ 1 michas users 1 18. Jan 16:57 99 -> /dev/random
Now the default descriptors do no longer point to your terminal but to the corresponding redirects. (As you see, you can also create new fds.)
One more example for <>
:
echo -e 'line 1\nline 2\nline 3' > foo # create a new file with three lines
( # with that file redirected to fd 5
read <&5 # read the first line
echo "xxxxxx">&5 # override the second line
cat <&5 # output the remaining line
) 5<>foo # this is the actual redirection
You can do such things, but you very seldom have to do so.
Best Answer
Summary
Under
bash
, if that command is in a script, the script file will be overwritten with an error message.Example
Consider the script:
Now, run the script:
Observe the new contents of the script:
Explanation
The command,
date 2&>$0
, is interpreted as follows:The
date
command is run with argument2
All output, both stdout and stderr, from the date command is redirected to the file
$0
.$0
is the name of the current script.The symbol
>
indicates redirection of, by default, stdout. As abash
extension, the symbol&>
is a shortcut indication redirection of both stdout and stderr. Consequently, both stdout and stderr are redirected to the file$0
.Once the script file is overwritten, it is no longer a valid script and
bash
will complain about the malformed commands.Difference between
bash
and POSIX shellsWith a simple POSIX shell, such as
dash
, the shortcut&>
is not supported. Hence, the commanddate 2&>$0
will redirect only stdout to the file$0
. In this case, that means that the script file is overwritten with an empty file while thedate
error message will appear on the terminal.