14

What is the design rationale that cat doesn't take list of file names from pipe input? Why did the designers choose that the following does not work?

ls *.txt | cat

Instead of this, they chose that we need to pass the file names as argument to cat as:

ls *.txt | xargs cat
Mert Nuhoglu
  • 9,695
  • 16
  • 79
  • 117

2 Answers2

9

When you say ls *.txt | cat doesn't work, you should say that doesn't work as you expect. In fact, that works in the way it was thought to work.

From man:

cat - Concatenate FILE(s), or standard input, to standard output

Suppose the next output:

$ ls *.txt
file1.txt
file2.txt

... the input to cat will be:

file1.txt
file2.txt

...and that's exactly what cat output in the standard output

In some shells, it's equivalent to:

cat <(ls *.txt)

or

ls *.txt > tmpfile; cat tmpfile

So, cat is really working as their designers expected to do so.


On the other hand, what you are expecting is that cat interprets its input as a set of filenames to read and concatenate their content, but when you pipe to cat, that input works as a lonely file.

whoan
  • 8,143
  • 4
  • 39
  • 48
  • Thank you, that is a very simple and clear explanation. Especially, this line clarified the issue to me: `ls *.txt > tmpfile; cat tmpfile` – Mert Nuhoglu Oct 18 '14 at 20:45
  • Is there any reason not to just simply `cat *.txt`? – Andy Jul 29 '15 at 23:09
  • Yes, because I wanted to show that `ls *.txt | cat` works the same as `cat <(ls *.txt)` in the sense that it is reading from the standard input. – whoan Jul 29 '15 at 23:27
4

To make it short, cat is a command, like echo or cp, and few others, which cannot convert pipe redirected input stream into arguments.

So, xargs, is used, to pass the input stream as an argument to the command.

More details here: http://en.wikipedia.org/wiki/Xargs

As a former unix SA, and now, Python developer, I believe I could compare xargs, to StringIO/CStringIO, in Python, as it kind of helps the same way.

When it comes to your question: Why didn't they allow stream input? Here is what I think

Nobody but them could answer this.

I believe, however, than cat is meant to print to stdout the content of a file, while the command echo, was meant to print to stdout the content of a string.

Each of these commands, had a specific role, when created.

DevLounge
  • 8,313
  • 3
  • 31
  • 44
  • I believe that it can be answered considering the design principles of Unix because `cat` is a very common command. So every design decision in `cat` are most probably made deliberately. – Mert Nuhoglu Oct 18 '14 at 20:21
  • Yes, exactly, see my edited answer. Unix has tons of principles, and each of the base shell commands have a specific role they have been created for. – DevLounge Oct 18 '14 at 20:24
  • Why do you say `cat` doesn't accept pipe redirection? In fact, it works fine as a filter. – whoan Oct 18 '14 at 20:37
  • Ooops, corrected, indeed. I meant it is a different usage. And doing a pipe to cat is like redirecting stdout to stdout and most of the time has no real interest. – DevLounge Oct 18 '14 at 20:41