6

Why does

echo "hello world" | cat

works while

cat < echo "hello world"

does not? My (incorrect) intuition is that pipe would redirect stdout to cat as stdin.

  • 2
    I guess it has something to do with the fact that a pipe is different from a redirection. From the manual of bash, it seems that you can only redirect a file as input. – Pierre-Alain TORET Nov 12 '15 at 13:53
  • 1
    In bash you can do cat <<< "hello word", if interested you can do man bash and search for Here Strings. – Hastur Nov 12 '15 at 14:10
8

We have two similar but different things

  • A pipeline

    echo "hello world" | cat   # This is a pipeline
    

    The pipe control operators (| and |&) connect the output of a command to the input of the following one in the pipeline. So the first example works, the output of the echo command, "Hello word", is connected with the input of the following cat command, that assumes the standard input as input file if not else specified. Indeed we can read from man cat:

    cat - concatenate files and print on the standard output

    and below the example with the simple invocation of cat

    cat Copy standard input to standard output

  • A redirection, or better an attempt of input redirection <

    cat < echo "hello world"   # This is an attempt of redirection 
    

    In this case cat command is taking its input from the standard input that you redirect with the operator < from the file on the right side of <... that is not a file. This is because it doesn't work.

    From the redirection section of the man bash

    Redirecting Input
    Redirection of input causes the file whose name results from the expansion of word to be opened for reading on file descriptor n, or the standard input (file descriptor 0) if n is not specified.

  • In bash it works for different reasons

    • cat <(echo "hello world") Process Substitution

      Process substitution is supported on systems that support named pipes (FIFOs) or the /dev/fd method of naming open files. It takes the form of <(list) or >(list). The process list is run with its input or output connected to a FIFO or some file in /dev/fd. The name of this file is passed as an argument to the current command as the result of the expansion. If the >(list) form is used, writing to the file will provide input for list. If the <(list) form is used, the file passed as an argument should be read to obtain the output of list.

    • cat <<< $(echo "hello world") Here Strings

      The word undergoes brace expansion, tilde expansion, parameter and variable expansion, command substitution, arithmetic expansion, and quote removal. Path-name expansion and word splitting are not performed. The result is supplied as a single string to the command on its standard input.

References

  • man bash and search for redirection, pipeline, Here Strings and Process substitution
  • man cat just because we use it...
0

That stream reads from files. > is out to a file and < is in from a file. Demonstration:

First echo "HELLO HELLO HELLO" > HELLO.txt and then cat < HELLO.txt gets you output

 HELLO HELLO HELLO

Kinda useless since the output already goes where you'd want, but another example with the same HELLO.txt is cat < HELLO.txt >&1 explicitly directing cat's output to STDOUT.

More usefully, you sometimes find file descriptor 2's output (STDERR) being redirected with commands like

grep somepattern /path/to/a_bunch_of_files/* 2>&1 >> alloutput.txt

The 2>&1 stream directs errors to standard output. Then all standard output is streamed to alloutput.txt. This would put error output in the file with standard output.

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.