That's specific to Linux. While on most Unices, opening
/dev/fd/n is more or less the same as
dup(n) (get a file descriptor to the same open file description as on fd
n), on Linux,
/dev/fd/n is a symlink to the file open on file descriptor
So, on Linux:
paste - /dev/fd/0 < file
is the same as:
paste - file < file
paste file file).
The two fds (0 for
- and the own obtained by opening
file), are independent and have their own cursor within the file.
You'll also notice that on Linux, you can't use /dev/fd/n with sockets.
Generally on Linux, you only want to use
/dev/fd/n with pipes. But in this case
cat file | paste - /dev/fd/0
(or switching to a non-Linux-based OS) won't really help.
paste - - works because
paste knows it's stdin in both cases. But not here, so it will read a whole chunk (as opposed to a single line) from
- (fd 0 to the pipe), and then another chunk from /dev/fd/0 (an independent fd to the same pipe on Linux, but whether those fds point to the same open file description or not doesn't matter for a pipe). Both
read()s will read separate parts of the file, but several lines at a time.
You'd need to tell
paste to read one byte at a time so it doesn't read more than one line from
- before reading a line from
/dev/fd/0, which you can probably not do without recompiling. You might be able to get
paste to read its stdin one byte at a time with
stdbuf, but probably not
$ cat file | paste - /dev/fd/0
$ cat file | stdbuf -i1 paste - /dev/fd/0