Useless use of cat

Discussion | Related

Discussion

“The purpose of cat(1) 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.”

That is to say, the following is wasteful.

$ cat file | wc -l

The above is better written in one of the two following methods.

$ wc -l < file
$ wc -l file

wc(1) accepts the file either as an argument on STDIN; which method to use depends on what you are doing. For instace, a useful use of cat and wc would be the following.

$ wc -l /etc/passwd
17 /etc/passwd
$ cat /etc/passwd /etc/group | wc -l
48

The useless cat file | styntax is seemingly attractive when doing something complex where one does not want to switch between a gzcat file.gz | grep 'complex expr' and a grep 'complex expr' file, for example, when looking through gziped log archives and uncompressed current logs for something. However, the redirect from the file can take place before the command.

$ <file grep 'complex expr' | …
$ gzcat file.gz | grep 'complex expr' | …

The redirect-before-command syntax usually works, though I have seen it fail near shell while loops in sh and bash. In shells where the following fails, the redirect must be done after the while statement. (Yes, the while loop here is useless. Imagine something complex if you must.)

$ 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

I currently use zsh, by the way.

Back on topic with the useless use of cat theme, a while read loop can be used in place of a cat something for loop in the shell. Furthermore, a while read loop can be extended to read in additional parameters as needed.

$ for i in `cat input`; do echo $i; done
a
b
c
$ while read i; do echo $i; done < input
a
b
c
$ (echo a b; echo c d) | \
while read one two; do echo $two $one; done

b a
d c

Related