wc
takes the list of files whose bytes/chars/w
ords/lines to c
ount as arguments.
When called with no argument, it reports those bytes/chars/words/lines in its stdin. So if you're piping find
to wc -l
, you'll get the number of newline characters in the output of find
, so that'll be the number of found files plus the number of newline characters in their paths.
The GNU implementation of wc
can also take the list of files NUL-delimited from a file with the --files0-from
option, where it treats -
as meaning stdin (not the file called -
), so you can do:
find . -name package.json -type f -print0 |
wc -l --files0-from=-
With any standard find
or wc
implementation, you could get find
to pass the list of file paths as arguments to wc
with:
find . -name package.json -type f -exec wc -l {} +
But if there's a large number of matching files, that could end up running wc
several times resulting in several occurrences of a total
line.
wc
prints the total
line when given at least 2 files to process, so to skip the total
line, you could do:
find . -name package.json -type f -exec wc -l {} ';'
Though that would be very inefficient as forking a process and executing a command for each file is quite expensive.
If it's the total you're actually interested in, then you'd do:
find . -name package.json -type f -exec cat {} + | wc -l
Where we feed the concat
enation of the contents of those files to wc
.
With zsh
and any wc
, you could do:
wc -l -- **/package.json(D.)
(D
for D
otglob to get hidden ones as well like find
does and .
to only include regular files as the equivalent of -type f
).
That has the advantage of giving you a sorted list and avoid the ./
prefix.
This time, if there are no or too many matching files, you'll get an error.
With GNU du
, you can avoid those by passing the glob expansion NUL-delimited to wc -l --files0-from=-
with:
print -rNC1 -- **/package.json(ND.) | wc -l --files0-from=-
Also beware that in the json format, newline characters (which wc -l
counts) are not significant so I'm not sure that's a useful metric you're getting.
You could return the number of elements in some array in those files for instance instead with:
find . -name package.json -type f -exec \
jq -r '[.devDependencies|length,input_filename]|@csv' {} +
(assuming the file paths are UTF-8 encoded text and here giving you the result in CSV format).
xargs
, there's also other whitespace characters, quotes and backslashes and with somexargs
implementations non-text file names. For$(...)
there are all the characters of$IFS
(by default also includes TAB) and the wildcard ones. It may apply here as the directories those package.json files are found in may very well contain those characters. – Stéphane Chazelas Jan 06 '23 at 21:16--print0
onfind
, and-0
onxargs
. I have never found a problem yet. – ctrl-alt-delor Jan 07 '23 at 00:02-0
here, so the problem is with a bunch of characters (and non-characters), not just space. – Stéphane Chazelas Jan 07 '23 at 10:55-print0
set out to heal and considered them unimportant for a quick typed command rather than an unattended script. i know that blanks god beware/home/hacker/\ /etc/shadow
break functionality but since they are rare in$pkgdir/package.json
trees i figured the obvious shorthands were missing first. i had not initially realized stéphane had consciously avoided them nor thefind -exec +
addition. unminding repetitiveness i had realized stéphane had already answered the question although silent about the quick hacks.**/package.json
direction my favorite. – Roman Czyborra Jan 07 '23 at 11:24