
“The purpose of cat is to concatenate (or "catenate") files. If it's only one file, concatenating it with nothing at all is a waste of time, and costs you a process.” — Randal L. Schwartz. The following example reads the contents of file twice, once with cat(1), and again with the second program:
$ cat file | wc -l
Eliminate this useless cat(1) via one of the following methods:
$ wc -l < file
$ wc -l file
wc(1) accepts the file either as an argument or standard input; the best method to use depends on the task. For instance, a rare useful use of cat is to count of lines from multiple files:
$ wc -l /etc/passwd
17 /etc/passwd
$ cat /etc/passwd /etc/group | wc -l
48
The useless cat file | … syntax may seem attractive when fiddling around with the … commands that follow the pipe, instead of navigating the shell back to the expression in grep -options expression < file. However, shells parse the redirect statements prior to executing the command, again eliminating the need for the useless cat via the following notation:
$ <file grep foo
$ <file grep bar
The redirect-before-command syntax fails before while loops in the sh and bash shells. In these shells, the redirect must be done after the while statement. This is one of several reasons I use zsh:
$ echo foo > file
$ <file while read l; do echo $l; done
while: not found
bash-2.05a$ <file while read l; do echo $l; done
bash: syntax error near unexpected token `do'
zsh-4.0.4$ <file while read l; do echo $l; done
foo
Other while caveats perhaps worth mentioning: while loops may interact poorly with commands such as ssh. Also, a while loop may not act on the ultimate line, if that line lacks an ultimate newline character.
Another useless use of cat is to hide the terminal:
$ echo foo >file
$ perl -ple 'print "terminal!" if -t' file
terminal!
foo
$ cat file | perl -ple 'print "terminal!" if -t'
foo
This may be required should the command behave differently on a terminal, and the non-terminal behavior is desired. However, again, there are solutions that do not involve the needless inefficiency of cat. Using the prefix notation, the data can be passed on standard input, which moves standard input of the subsequent program away from the terminal:
$ <file perl -ple 'print "terminal detected" if -t'
foo
The second method is to close standard input. The filename is read by the program itself, not needlessly by cat:
$ perl -ple 'print "terminal detected" if -t' file <&-
foo
The tty(1) command shows how closing standard input hides the terminal:
$ tty
/dev/ttyp1
$ tty <&-
not a tty