I am trying to understand input redirection in combination with process substituation. I am using bash 3

An example with tr is the following

$ tr "o" "a" <(echo "Foo")
tr: extra operand `/dev/fd/63'
Try `tr --help' for more information.

I think I understand why this does not work. The process substitution <( ) creates a file descriptor, where tr only reads from standard input.

How can I make it work with proper redirection?

I know that I could simply use pipes:

$ echo "Foo" | tr "o" "a"

However, I am trying to get a better understanding. I tried some thing with the help of man bash, by using <&, but I don't really know what I am doing.

How can I use process substitution properly using tr?

2 Answers 2


You were really close:

tr "o" "a" < <(echo "Foo")

The substitution <() makes a file descriptor and just pastes the path to the shell. For comprehension just execute:

<(echo blubb)

You will see the error:

-bash: /dev/fd/63: Permission denied

That's why it just pastes /dev/fd/63 into the shell and /dev/fd/63 is not excutable, because it's a simple pipe. In the tr-example above, it's echo "Foo" that writes to the pipe and via input redirection < it's the tr command that reads from the file descriptor.

  • Aah, of course, I did try <<( :o. Thanks!
    – Bernhard
    Commented Sep 2, 2014 at 11:00
  • 5
    ls -ld <(echo blubb) may be a better illustration. Commented Sep 2, 2014 at 11:47

I found the Bash One-Liners Explained series very useful in understanding more about all this stuff.

Specifically the article linked above is all about input redirection.

To solve the specific example above:

> tr "o" "a" <<< $(echo "Foo")
  • This is using a "here-string", but does not do any input redirection. Although it is possible on my question, for multi-line input it breaks (as far as I can see from my tests)
    – Bernhard
    Commented Sep 2, 2014 at 10:59
  • 4
    @Bernard. It does redirection. First it runs echo Foo in a subshell with its output redirected to a pipe. It reads that output from the other end of the pipe and stores it (minus the trailing newline characters). Once eof is reached on that pipe, depending on the shell, it performs word splitting on that and joins the resulting words with space (bash) or not (zsh, ksh93). And then stores that and a newline into a temporary file. Then tr input is redirected from that temporary file. Commented Sep 2, 2014 at 11:53
  • @StéphaneChazelas (was not notified by your remark). I did not know the here-string also uses temporary files, but that makes sense. Thank you.
    – Bernhard
    Commented Sep 2, 2014 at 14:37

You must log in to answer this question.

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