That will show you what files correspond to what file descriptors for your current shell process. You can then experiment with redirects. To see how a pipe works we can do something similar:
Anyway, thinking of `>` and `<` as just FD setters made things a lot clearer for me personally. They just set the file descriptor on the left to file on the right and `&n` can be used to "dereference" a FD to its corresponding file. The only real difference between `>` and `<` is that the former opens the file with write permission while the latter opens it with read. Well, and the default FDs are different.
Incidentally, this makes it clear why the following doesn't work as expected:
$ curl 'https://kernel.org/' >/dev/null 2>&1 | tee curl.errs
Since FDs get set in the order they are specified, 1 gets set to /dev/null and then 2 gets set to whatever 1 is, i.e /dev/null. So it's clear that we probably intended the following:
$ curl 'https://kernel.org/' 2>&1 >/dev/null | tee curl.errs
Which lets us ignore stdin and maybe pipe stdout to some other command.
Now I hope Linus doesn't hate on me for abusing kernel.org :P
Edit: I've done some more testing, and discovered that the above works on zsh, but not in bash
2nd Edit: Ahha! http://www.cs.elte.hu/zsh-manual/zsh_7.html . So this is because zsh w/ the stock config (MULTIOS option enabled) will open as many outputs as you give it. So it can both copy FD 1's contents to FD 2 and to the pipe'd command.
Also, I noticed you can rewrite this function:
as a oneliner without needing process substitution or echo: