How do I find files and total their sizes?

Solution

By supplying the option -c (or --total) to du(1), you can instruct it to produce a grand total. If your implementation of du(1) supports either of these options, you can achieve the desired effect using the following command:

$ find . -name 'flibble*' -ctime +90 -exec du -shc {} +

EDIT: Note that if the number of files exceeds the maximum number of parameters permitted by your system, find may still execute command multiple times. Some implementations of du(1) also support reading the filenames from a file, which does not suffer from the mentioned limitation:

$ find -name 'flibble*' -ctime +90 -print0 > filenames
$ du -shc --files0-from=filenames

Explanation

The difference between the semantics of -exec command {} \; and -exec command {} + is the following:

  • command {} \; executes command once for each result of find. The pathname of the result is passed instead of {}.

    $ touch 1 2 3
    $ find  1 2 3 -maxdepth 0 -exec echo {} \;
    1
    2
    3
    
  • command {} + executes command, when all the results have been retrieved. The pathnames of the results are passed instead of {}.

    $ touch 1 2 3
    $ find  1 2 3 -maxdepth 0 -exec echo {} +
    1 2 3
    

The -print0 option causes find(1) to print the found filenames to the standard output separated by the null character, and the --files0-from option caused du(1) to read the null-separated filenames. Unlike the new line character, the null character may not appear in a filename, so the output is unambiguous.

To learn more about the options of du(1) and find(1), you should consult the respective manpages:

$ man du
$ man find

Try this:

du -c `find . -name 'flibble*' -ctime +90` | tail -1

The original command is giving du one argument, then executing it, until it goes through all the arguments. This way, you simply are giving it all the arguments at once, then cutting off the separate sizes, and leaving only the total. You can remove the pipe and tail to show the size of each file if you'd like.


You can try this:

find . -name 'flibble*' -ctime +90 -exec du -ch {} + | grep total

Tags:

Linux

Bash