ZmRR
ZmRR

Reputation: 9

Why does "ls > out | cat < out" only output the first time I run it in Bash?

I am programming a Bash-like shell. I am having trouble understanding how this interaction works.

This command

ls > out | cat < out

only outputs the ls the first time I run it, and then nothing. In zsh it outputs everytime but not in Bash.

Upvotes: 0

Views: 108

Answers (1)

Paul Hodges
Paul Hodges

Reputation: 15273

You're trying to give the parser conflicting directives.
This is like telling someone to "Turn to the left on your right."

<, >, and | all instruct the interpreter to redirect I/O according to rules.

Look at this bash example:

$: echo two>two # creates a file named two with the word two in it
$: echo one | cat < two <<< "three" << END
four
END
four

$: echo one | cat < two <<< three
three

$: echo one | cat < two
two

$: echo one | cat
one

Understand that putting a pipe character (|) between commands links the output of the first one to the input of the second one, so also giving each an input/output redirection that conflicts with that is nonsensical.

ls | cat             # works - output of ls is input for cat
ls > out; cat < out  # works - ls outputs to out, then cat reads out 
ls > >(cat)          # works 
cat < <(ls)          # works

but ls >out | cat sends the output from ls to out, and then attaches the output of that operation (of which there is none, because it's already been captured) to cat, which exits with no input or output.

If what you wanted was to have the output both go to a file and to the console, then either use ls > out; cat < out which makes them separate operations, or try

ls | tee out

which explicitly splits the stream to both the file and stdout.

Upvotes: 1

Related Questions