-1
$ ls
1.txt   2.txt   3.txt
$ ls | wc
       3       3      18

All three files has only 1 line, but ls|wc outputs '3'.

  • 1
    What were you expecting it to output? It sounds like you thought it would give you the number of lines in each file, is that right? – terdon Nov 19 '18 at 16:28
  • I'm voting to reopen this. I don't think that the user is actually trying to count the number of lines from the ls command, but from the individual files. – Kusalananda Nov 19 '18 at 20:25
  • 1
    Reluctantly VTO. Alexandr, you need to [edit] your question to explain more clearly what you were expecting. – Chris Davies Nov 19 '18 at 23:50
  • Now I realise that I don't know what the question is. Please clarify. (3 × 1 is 3, so should not be unexpected). – ctrl-alt-delor Nov 20 '18 at 08:01

3 Answers3

5

Try ls | cat to see how ls formats output differently when piped, compared to when sent to terminal.

  • Is this what the OP meant? It sounds like they were expecting a count of the lines in each file: "All three files has only 1 line, but ls|wc outputs '3'.". – terdon Nov 19 '18 at 16:28
3

ls, when outputting to anything other than a terminal, behaves like ls -1 (that's the digit 1, not "ell") and outputs each name on a new line.

If you would want to count the number of line in the ls output as it would have appeared had it not been piped at all, use ls -C. The -C option to ls forces multi-column output regardless of where that output is directed.

That is, use

ls -C | wc

or, to just get the line count,

ls -C | wc -l

On the other hand, if you wanted to count the number of lines in the three files, individually, you would have used

wc -l -- *

This would, if each file contained exactly one line, result in the output

   1 1.txt
   1 2.txt
   1 3.txt
   3 total

That is, each file contains one line, and the total number of lines in the three files is three.

The difference between wc -l -- * and ls -C | wc -l (or, ls | wc as you wrote), is from where wc gets its input.

With ls -C | wc -l, wc reads from the output of ls and would therefore count the number of lines that the ls command produced. Not the number of lines in any file.

With wc -l -- *, we tell wc to read specific files. In this case, the files corresponding to the names that the wildcard ("filename globbing pattern") * expands to.

wc -l -- * is equivalent to wc -l -- 1.txt 2.txt 3.txt if those are the only files in the directory.

Note that if one the files in the current directory is called -, that wouldn't work properly as wc interprets a - argument as meaning standard input. One way to work around that would be to use wc -l ./* instead (./- is not special to wc), but that means that ./ prefix will also show in the output of wc.

Kusalananda
  • 333,661
  • 1
    Is this what the OP meant? It sounds like they were expecting a count of the lines in each file: "All three files has only 1 line, but ls|wc outputs '3'.". – terdon Nov 19 '18 at 16:29
  • @terdon Thanks! I might have overlooked that. I will make an addition about it. – Kusalananda Nov 19 '18 at 18:23
1

ls is giving you 3 columns which is different than single line, thus wc is counting new line after each column end. In other words, ls outputs formatted text, even though you don't see that. But wc does.

  • a single line of 3 columns wouldn't have 3 newlines – Jeff Schaller Nov 19 '18 at 11:58
  • Sorry for my bad english. What i wanted to say is that ls is giving thre lines a s a result, formatted in three columns. wc counts actual new lines that poster doesn't see. Would that be better explanation? – Igor Smitran Nov 19 '18 at 12:31