Can't they just directly access inodes for high speed counting?
Can't they just directly access inodes for high speed counting?
Available in most repositories, source code available at: http://mama.indstate.edu/users/ice/tree/
Don't know what you mean by that exactly. But, I'd be stunned if find is actually reading the actual files rather than just reading the directory entries in directory "files". Which is what I'd call accessing inodes "directly"
Compared to the equivalent find, code #1 is much faster in this completely scientific best of several runs:
$ time (find OSS/llvm -type f -or -type l | wc -l)
real 0m4.681s
$ time du -d0 OSS/llvm
real 0m4.863s
$ time ./fts OSS/llvm
real 0m0.559s
Ostensibly because of the lack of stat calls. On the other hand the second paste and find with no arguments are equivalent.edit: screwed up benchmarks
function lc() { if [[ "$#" -gt 1 ]]; then for DIR in "$@"; do echo -n "$DIR - " ; ls -AU1 $DIR | wc -l ; done ; else ls -AU1 "$@" | wc -l ; fi; }
Then "lc dir/" will print the number of files in the directory, and "lc dir/*" will print the number of files in each of the subdirectories. This exactly what you're looking for because it doesn't descend into the tree. If you're working with directories that may have tens or hundreds of thousands of files in them, it's useful to check first.
imac:~
$ time find . | wc -l
419191
real 0m37.865s
user 0m0.385s
sys 0m2.611s
imac:~
$ time find . | wc -l
419195
real 0m10.503s
user 0m0.330s
sys 0m1.430sWhat do you do when find cannot handle the sheer number of files, argument too long from the linux hardcoded MAX_ARG_PAGES
We need a dedicated utility that counts inodes.
Also, to count the number of files in a directory, you need to do readdir(), which will get you the names. Then, to see if any of them are directories to be recursed into you need to stat() the names individually. This is all "find" does. How, I'd very much like to know, is this "a nasty hack"?
All we want from find is "count the number of inode entries in this tree branch that are type f". No formatting, no output, just count. That has to be much more efficient.
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux....
That's "time find . | wc -l"
It's going to be disk limited unless you're in cache.
Switching to "time find . -printf '1' | wc -c" lowers overhead to .7 seconds, so roughly 1us/file.
The output from find is a list of filenames separated by newlines. The wc command is reading from stdin and counting those newlines[1] -- wc itself has just two arguments in its argv array here ("wc", "-l"). You will not exceed its argument list. Further, it is not at all a hack to count the number of files this way; rather using pipes to compose functionality is the Unix way[2].
But fwiw, if you want a count of the inodes in use in the entire filesystem, you can get that directly from "df -i".
In any case, as an exercise to the reader, I encourage you to grab the source to find and add the -count output option you desire.
[1] Technically a filename can contain newlines, so this would throw off the count. The fix for that would be to use find's -print0 output option and then pipe to something which can count on the nulls. In practice, you're unlikely to have such filenames.
If your locatedb is current, you can use locate for this:
$ locate $PWD | wc -l
That runs in just a hair under a second (0.908s real) for the first instance. 'find' takes a few seconds on first pass (it's got to read from disk), but is surprising fast (0.227s real) on subsequent runs.So I guess it depends on whether you're doing it just once or multiple times.
find . | sed -e 's=/[^/]*$==' | uniq -c
tree | egrep -o "[0-9]+ file(s|)"
edit: or you could just tail the output (should have thought of this first!) tree | tail -n1