68

How can I count all lines of all files in all subdirectories with wc?

cd mydir
wc -l *
..
11723 total

man wc suggests wc -l --files0-from=-, but I do not know how to generate the list of all files as NUL-terminated names

find . -print | wc -l --files0-from=-

did not work.

Jonas Stein
  • 6,826
  • 7
  • 40
  • 72

7 Answers7

115

You probably want this:

find . -type f -print0 | wc -l --files0-from=-

If you only want the total number of lines, you could use

find . -type f -exec cat {} + | wc -l
gniourf_gniourf
  • 44,650
  • 9
  • 93
  • 104
9

Perhaps you are looking for exec option of find.

find . -type f -exec wc -l {} \; | awk '{total += $1} END {print total}'
7

To count all lines for specific file extension u can use ,

find . -name '*.fileextension' | xargs wc -l

if you want it on two or more different types of files u can put -o option

find . -name '*.fileextension1' -o -name '*.fileextension2' | xargs wc -l
Ankur
  • 330
  • 2
  • 8
  • 17
  • 5
    This breaks on any file with whitespace or `\` in its name. See the [accepted answer](http://stackoverflow.com/a/13728131/1081936) for how to use this approach correctly. – terdon Sep 30 '14 at 13:31
  • Love this solution even if it's apparently not sufficient in all cases. Worked for my purposes like a charm. – wetjosh Mar 02 '22 at 01:28
4

Another option would be to use a recursive grep:

grep -hRc '' . | awk '{k+=$1}END{print k}'

The awk simply adds the numbers. The grep options used are:

   -c, --count
          Suppress normal output; instead print a count of matching  lines
          for  each  input  file.  With the -v, --invert-match option (see
          below), count non-matching lines.  (-c is specified by POSIX.)
   -h, --no-filename
          Suppress the prefixing of file names on  output.   This  is  the
          default  when there is only one file (or only standard input) to
          search.
   -R, --dereference-recursive
          Read all files under each directory,  recursively.   Follow  all
          symbolic links, unlike -r.

The grep, therefore, counts the number of lines matching anything (''), so essentially just counts the lines.

terdon
  • 3,260
  • 5
  • 33
  • 57
1

I would suggest something like

find ./ -type f | xargs wc -l | cut -c 1-8 | awk '{total += $1} END {print total}'
sge
  • 7,330
  • 1
  • 15
  • 18
  • everything that is not a directory; in most cases will be the same as -type f – sge Dec 05 '12 at 16:47
  • 3
    Except for block device nodes, character device nodes, named pipes, sockets, .... at least one of which will break the whole exercise... Best to stick to `-type f`... – twalberg Dec 05 '12 at 16:51
1

Based on ДМИТРИЙ МАЛИКОВ's answer:

Example for counting lines of java code with formatting:

one liner

find . -name *.java -exec wc -l {} \; | awk '{printf ("%3d: %6d %s\n",NR,$1,$2); total += $1} END {printf ("     %6d\n",total)}'

awk part:

{ 
  printf ("%3d: %6d %s\n",NR,$1,$2); 
  total += $1
} 
END {
  printf ("     %6d\n",total)
}

example result

  1:    120 ./opencv/NativeLibrary.java
  2:     65 ./opencv/OsCheck.java
  3:      5 ./opencv/package-info.java
        190
Wolfgang Fahl
  • 15,016
  • 11
  • 93
  • 186
-2

Bit late to the game here, but wouldn't this also work? find . -type f | wc -l

This counts all lines output by the 'find' command. You can fine-tune the 'find' to show whatever you want. I am using it to count the number of subdirectories, in one specific subdir, in deep tree: find ./*/*/*/*/*/*/TOC -type d | wc -l . Output: 76435. (Just doing a find without all the intervening asterisks yielded an error.)

Cronk
  • 453
  • 1
  • 6
  • 16