41

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?

38

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.

  • 5
    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 Sep 17 '14 at 19:15
  • 6
    There is no named pipe here. /dev/fd/63 is an anonymous pipe. – Gilles 'SO- stop being evil' Sep 17 '14 at 21:06
  • 1
    @crater2150, @Gilles /dev/fd/63 is indeed a named pipe. Check this with something like file <(ls). The shell does create an anonymous pipe, but the file descriptor reflects as a named pipe in /dev/fd. If it were an anonymous pipe, it would not have a name and could not be opened by a command to which /dev/fd/63 is passed. – r.v Feb 8 '16 at 19:35
  • 2
    @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. – Gilles 'SO- stop being evil' Feb 8 '16 at 20:00
  • 1
    Why is it 63, though? – K3---rnc Sep 5 '17 at 21:24
-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.

  • 1
    There is no redirection from a file here. <(…) is a process substitution. – Gilles 'SO- stop being evil' Sep 17 '14 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 Sep 18 '14 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 Sep 18 '14 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 Sep 18 '14 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 Sep 18 '14 at 20:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.