57

I am trying to understand named pipes in the context of this particular example.

I type <(ls -l) in my terminal and get the output as, bash: /dev/fd/63: Permission denied.

If I type cat <(ls -l), I could see the directory contents. If I replace the cat with echo, I think I get the terminal name (or is it?).

echo <(ls -l) gives the output as /dev/fd/63.

Also, this example output is unclear to me.

ls -l <(echo "Whatever")
lr-x------ 1 root root 64 Sep 17 13:18 /dev/fd/63 -> pipe:[48078752]

However, if I give,ls -l <() it lists me the directory contents.

What is happening in case of the named pipe?

2 Answers 2

64

When you do <(some_command), your shell executes the command inside the parentheses and replaces the whole thing with a file descriptor, that is connected to the command's stdout. So /dev/fd/63 is a pipe containing the output of your ls call.

When you do <(ls -l) you get a Permission denied error, because the whole line is replaced with the pipe, effectively trying to call /dev/fd/63 as a command, which is not executable.

In your second example, cat <(ls -l) becomes cat /dev/fd/63. As cat reads from the files given as parameters you get the content. echo on the other hand just outputs its parameters "as-is".

The last case you have, <() is simply replaced by nothing, as there is no command. But this is not consistent between shells, in zsh you still get a pipe (although empty).

Summary: <(command) lets you use the ouput of a command, where you would normally need a file.

Edit: as Gilles points out, this is not a named pipe, but an anonymous pipe. The main difference is, that it only exists, as long as the process is running, while a named pipe (created e.g. with mkfifo) will stay without processes attached to it.

7
  • 7
    mkfifo only creates the named pipe, without any content. So you need to write to it yourself (e.g. mkfifo mypipe; ls > mypipe). And yes, the writes to the pipe will block until some process reads from the pipe.
    – crater2150
    Commented Sep 17, 2014 at 19:15
  • 12
    There is no named pipe here. /dev/fd/63 is an anonymous pipe. Commented Sep 17, 2014 at 21:06
  • 5
    @r.v It's still an anonymous pipe. The fact that there is a file name that refers to this anonymous pipe doesn't make it a named pipe: a named pipe is different, it exists somewhere on a filesystem, has permissions and ownership, etc. Entries of /dev/fd can refer to any file descriptor, even anonymous pipes and sockets, network sockets, shared memory segments, etc. Commented Feb 8, 2016 at 20:00
  • 4
    Why is it 63, though?
    – K3---rnc
    Commented Sep 5, 2017 at 21:24
  • 4
    @K3---rnc The exact path that the pipe will have is not fixed and may differ between shells or even versions of the shell. So the 63 is just some non-reserved file descriptor, that bash seems to pick by a deterministic method.
    – crater2150
    Commented Sep 8, 2017 at 15:49
-4

You misunderstand both the ls command and redirection. ls lists the files and directories given on the command line, I don't believe it accepts any input from stdin. Redirection > >> and < are ways to use a file to give input and collect output.

10
  • 2
    There is no redirection from a file here. <(…) is a process substitution. Commented Sep 17, 2014 at 21:05
  • 1
    @IMSoP - as Gilles said - its not a named pipe - its an anonymous pipe. It is very much the same as x|y and nearly identical to [num]<<REDIRECT in some shells. Where it differs is the shell's literal substitution of the fd link - /dev/fd/63 and etc and what it does - or doesnt do - with stdin. Do echo | readlink /dev/fd/0 and see for yourself.
    – mikeserv
    Commented Sep 18, 2014 at 5:12
  • 1
    @IMSoP - that's a dev link - a special file. you can do the same w/ any file descriptor on most linux systems - even typical |pipes, though i wont vouch for the behavior elsewhere. i get where youre coming from, but a named pipe is a separate thing unto itself - it is a file-system reference to an in-kernel pipe - a regular file-system reference, not a device file.
    – mikeserv
    Commented Sep 18, 2014 at 8:59
  • 1
    @mikeserv Interestingly, the Bash manual mentions that it will work on systems without /dev/fd/* by creating a named pipe somewhere else. But I take the point that /dev/fd/* itself is a different mechanism than a named pipe proper. Incidentally, Wikipedia's description could do with an explanation of this distinction.
    – IMSoP
    Commented Sep 18, 2014 at 17:40
  • 1
    @mikeserv According to other references I found, it's simpler than that: if /dev/fd/* isn't available, bash will make a named pipe in /tmp, and use that for process substitution instead. Doesn't seem so weird to me, just making the functionality available in as many environments as possible.
    – IMSoP
    Commented Sep 18, 2014 at 20:25

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .