Search code examples
bashcat

Bash - cat command and errors


I was trying bash shell redirection. I have a directory where there is just one file - a.txt

more a.txt
HELLO

If I type cat < a.txt b.txt , I get

cat: b.txt: No such file or directory

If I type

cat  < a.txt   b.txt a.txt

I get

cat: b.txt: No such file or directory
HELLO

Why am I not seeing HELLO when I try cat < a.txt b.txt? I tried different combinations - typing a.txt multiple times before/after b.txt and see a pattern, but not able to figure out why.

cat  <   a.txt a.txt b.txt  
HELLO
cat: b.txt: No such file or directory

Solution

  • Redirecting means sending the content of the file into the command's STDIN.

    cat's behavior is to read content of file in it's argument(s) to STDOUT. But if there's no argument, then the content is read from STDIN.

    See that I write argument(s) there? It's because the number of argument can be 0, 1, or multiple.

    in simple pseudocode, it's like this:

    if number of arguments = 0
      print STDIN to STDOUT
    else
      for each file in arguments
        print file content to STDOUT
    

    Example 1:

    cat a.txt

    output:

    HELLO

    Example 2:

    cat (then enter)

    You will be able to type into terminal, when you click enter, the typed line is sent to cat's STDIN. Then cat will print line you just typed.

    Answer

    So when you type:

    cat < a.txt b.txt

    internally, it works like this:

    • STDIN is filled with content of a.txt HELLO text
    • $1 (first argument) is b.txt which is a non-existent file

    based on behavior above, it will print content of b.txt alone since there is 1 argument supplied.

    but it doesn't find file b.txt, so it outputs an error message.

    when you type:

    cat < a.txt b.txt a.txt

    internally, it works like this:

    • STDIN is filled with content of a.txt HELLO text
    • $1 (first argument) is b.txt which is a non-existent file
    • $2 (second argument) is a.txt

    will output: (once again STDIN is ignored because there are 2 arguments)

    cat: b.txt: No such file or directory
    HELLO
    

    More detailed explanation

    • when you run command mycommand arg1 arg2 arg3, it means there are 3 command line arguments: arg1, arg2, arg3 respectively
    • STDIN is standard input: data stream for sending input to a command. You can send data to STDIN like these (assuming the target command is cat):
      • echo "my data" | cat
      • make file called data.txt, filled with my data, save it, then use cat < data.txt