0

Running wc -l (line count) individually on a file gives:

λ wc -l pacman_Qemq.txt
235 pacman_Qemq.txt

But running ls | xargs wc -l gives:

λ ls | xargs wc -l
  242409 pacman_database.tar.bz2
     235 pacman_Qemq.txt
     235 pacman_Qem.txt
     807 pacman_Qeq.txt
     807 pacman_Qe.txt
     376 pacman_Qmq.txt
    2276 pacman_Qnq.txt
    2276 pacman_Qn.txt
    2652 pacman_Qq.txt
    2652 pacman_Qsq.txt
    2652 pacman_Q.txt
  257377 total

How can this be? Why did the total show up? Why are the entries aligned? Shouldn't xargs be running wc -l individually on each file?

Interestingly, wc -l * produces the same result.

Mateen Ulhaq
  • 681
  • 7
  • 13

1 Answers1

5

By default, xargs will pass as many parameters on a single command line as it can - usually up to the shell limit of (IIRC) 256 characters. So the command you're using, ls | xargs wc -l, is functionally equal to wc -l *. The behavior I believe you're expecting is for xargs to run wc once for each file, which can be produced by adding the -n option, ls | xargs -n 1 wc -l.

Kusalananda
  • 320,670
  • 36
  • 633
  • 936
John
  • 16,759
  • 1
  • 34
  • 43
  • +1 - although the argument length limit is likely significantly larger than 256 characters. See for example [What is a canonical way to find the actual maximum argument list length?](https://unix.stackexchange.com/questions/45143/what-is-a-canonical-way-to-find-the-actual-maximum-argument-list-length) – steeldriver Jan 05 '20 at 14:36
  • Note the "functionally equal" commands that you mention are only functionally equal if the number of files in the current directory is small. Also, using `xargs -n 1 wc -l` on the right hand side would not work as soon as a filename contains a space, tab or newline. – Kusalananda Jan 05 '20 at 15:16