The cat command can do things that the shell can't necessarily do (or at least, can't do easily). For example, suppose you want to print characters that might otherwise be invisible, such as tabs, carriage returns, or newlines. There *might* be a way to do so with only shell builtin commands, but I can't think of any off the top of my head. The GNU version of cat can do so with the
-A argument or the
-v -E -T arguments (I don't know about other versions of cat, though). You could also prefix each line with a line number using
-n (again, IDK if non-GNU versions can do this).
Another advantage of cat is that it can easily read multiple files. To do so, one can simply type
cat file1 file2 file3. To do the same with a shell, things would get tricky, although a carefully-crafted loop could most likely achieve the same result. That said, do you really want to take the time to write such a loop, when such a simple alternative exists? I don't!
Reading files with cat would probably use less CPU than the shell would, since cat is a pre-compiled program (the obvious exception is any shell that has a builtin cat). When reading a large group of files, this might become apparent, but I have never done so on my machines, so I can't be sure.
The cat command can also be useful for forcing a command to accept standard input in instances it might not. Consider the following:
echo 8 | sleep
The number "8" will be not accepted by the "sleep" command, since it was never really meant to accept standard input. Thus, sleep will disregard that input, complain about a lack of arguments, and exit. However, if one types:
echo 8 | sleep $(cat)
Many shells will expand this to
sleep 8, and sleep will wait for 8 seconds before exiting. You can also do something similar with ssh:
command | ssh 22.214.171.124 'cat >> example-file'
This command with append example-file on the machine with the address of 126.96.36.199 with whatever is outputted from "command".
And that's (probably) just scratching the surface. I'm sure I could find more example of cat being useful if I wanted to, but this post is long enough as it is. So, I'll conclude by saying this: asking the shell to anticipate all of these scenarios (and several others) is not really feasible.