Useless use of `cat`
`cat file | cmd` spawns an extra process. Use `cmd < file` or `cmd file` instead.
Problem
`cat file | grep pattern` forks an extra process and uses a pipe where none is needed. `grep pattern < file` (or just `grep pattern file`) is shorter, faster, and lets the receiving command know the filename for error messages.
Bad
cat access.log | grep ERROR | wc -lGood
grep -c ERROR access.log
# Or, when you really need a pipeline starting from a file:
< access.log grep ERROR | wc -lExplanation
Almost every classic Unix tool can either take a filename or read from stdin via redirection. Reaching for `cat` is rarely necessary and obscures what the pipeline actually does.
Related
SC2129
When It Matters
cat file | cmd spawns a process and a pipe to do what a redirection does for free, and it discards the ability of the receiving command to seek in the file. For grep, sed, and awk it also loses the filename in the output, which is why grep in a cat pipeline cannot prefix matches with the file it found them in. On very large files the extra copy through the pipe is measurable; on many small files inside a loop, the extra fork dominates.
Second Example
Note
$(< file) is a Bash optimisation that reads the file directly in the shell, avoiding both cat and the pipe.
Exceptions
cat earns its place when you are concatenating several files, when you need it to number lines or squeeze blanks, or when the receiving command genuinely only accepts stdin and you want to combine sources. Those uses are not what the warning is about.
Faq
Q
Is the performance difference real?
A
For one invocation it is negligible. Inside a loop over thousands of files, or on multi-gigabyte inputs, the extra process and pipe copy are easily measurable.
Q
Why does grep behave differently in a pipeline?
A
Given filenames, grep prefixes matches with the filename when there is more than one and supports options like -l and -r. Reading stdin it has no filename to report.
Q
What about cat with a heredoc?
A
cat <<EOF is a common idiom for emitting a block of text and is unrelated to this warning.