I’ve been reading an excellent book called The Linux Programming Interface. In the book, Michael gives a tip on how you can use stdin as an argument to shell commands.

For example, let’s say you want to diff the output of ls against a previous output that was saved in a file called oldls.txt.

One way you could do it is as follows: ls | diff - oldls.txt

However, what about utilities that don’t implement the - option?

He gives an alternate approach which I found to be really novel: ls | diff /dev/stdin oldls.txt

This works because /dev/stdin is a symlink to a file representation of file descriptor 0 located at /proc/self/fd/0.

If I look at /proc/self/fd/0 I see it is a symlink to my pseudo terminal:

% ls -al /proc/self/fd/0
lrwx------ 1 mattjbarlow mattjbarlow 64 Oct 28 11:27 /proc/self/fd/0 ->
/dev/pts/15

In fact, file descriptor 0, 1, and 2 are all symlinks to my pseudo terminal:

% ls -al /proc/self/fd/{0,1,2}
lrwx------ 1 mattjbarlow mattjbarlow 64 Oct 28 11:14 0 -> /dev/pts/15
lrwx------ 1 mattjbarlow mattjbarlow 64 Oct 28 11:14 1 -> /dev/pts/15
lrwx------ 1 mattjbarlow mattjbarlow 64 Oct 28 11:14 2 -> /dev/pts/15

It seems strange that they are all linked to the same file. But, it makes sense because, in the moment I run the ls command, my terminal is the source for stdin, and the output for stdout and stderr.

In fact, these symlinks change per-process, which can be demonstrated with the following command:

% echo "test" | ls -al /proc/self/fd/0
lr-x------ 1 mattjbarlow mattjbarlow 64 Oct 28 11:42 /proc/self/fd/0 -> 'pipe:[20437852]'

For more information on command redirection, I recommend the following lab note