Search code examples
linuxpipecatls

Why is `ls hello.txt | cat` different from `cat hello.txt`?


I wonder why ls hello.txt|cat does not do the same thing as cat hello.txt? I am trying to pass the result of ls to cat, which seems to make sense, because the result of 'ls hello.txt' is hello.txt itself.


Solution

  • If you pipe in input to cat, the result is the input. That's how cat handles stdin. In general, programs are supposed to treat stdin differently than they treat arguments.

    Maybe these can help you see it a bit clearer:

    echo "hello" | cat
    => hello
    

    echo "hello" feeds in "hello" to cat, and cat's behavior with stdin is just to print out whatever it receives in stdin. So it prints out "hello".

    cat hello.txt | cat
    => prints out the text of hello.txt
    

    The first cat outputs the contents of file.txt, and the second cat outputs whatever it receives in stdin -- file.txt's contents.

    So, what does ls hello.txt output?

    ls hello.txt doesn't output the text inside hello.txt. Instead, it literaly just outputs the string "hello.txt" if the file exists:

    ls hello.txt
    => hello.txt
    
    ls hello.txt | cat
    => hello.txt
    

    just like how:

    echo "hello"
    => hello
    
    echo "hello" | cat
    => hello
    

    I guess maybe one of the big misunderstandings might be that you're thinking ls hello.txt outputs the contents of hello.txt...but it doesn't, it just outputs the name. And cat takes in that name, and prints the name right back out. The result of ls hello.txt is literally just the string "hello.txt"...it's not the contents of the file. And cat just outputs what it receives -- the string "hello.txt". (not the contents of the file)