25

I want to know the size of file with .o extension (object file) in my Home folder.

I can find all the object files using

find . -name '*.o'

How can I now calculate total size of those files?

4 Answers 4

36

You're looking for pipes (|). They are a way of connecting multiple commands and passing the output of one command as input to another. In this case, you want to pass all the file names you find as input to du (which calculates size). However, because du expects file names and the results of find are just a list of text (yes, the text consists of file names, but du can't know that, all it sees is text), you need to use something like xargs which will take each line of text, treat it as a file name and pass that to du. Putting all this together, we get:

find . -name "*.o" | xargs du -sch
  • you should always quote the patterns you give to find (as I did above: "*.o"). If you don't, the shell will expand the *.o to the names of any matching files in the current directory. It worked in this case only because you had no matching files.

  • The -sch flags for du are documented in man du:

    -c, --total
          produce a grand total
    -h, --human-readable
          print sizes in human readable format (e.g., 1K 234M 2G)
    -s, --summarize
          display only a total for each argument
    

Note, however, that this will fail for filenames containing whitespace. This is almost certainly not going to be an issue for object files, but in the future, if you also need to deal with spaces, use:

find . -name "*.o" -print0 | xargs -0 du -sch

The -print0 makes find print NULL-separated lines and the -0 makes xargs take such lines as input.

Alternatively, you can have find print the sizes itself and then sum them:

find . -name "*.o" -printf '%s\n' | awk '{c+=$1}END{print c}'

This will also get around the problem mentioned by @Serg in the comments where there are too many arguments and the command is broken into separate commands.


If you're using bash (you probably are), there's a simpler way:

shopt -s globstar 
du -sch **/*.o

The shopt globstar command makes ** match all files and or more subdirectories. After enabling it, **/*.o will match all files (and directories) whose name ends in .o, so we can pass that directly to du.

Note that, unlike the find approach, this won't match hidden files (those whose name starts with a .). To match those as well, do:

shopt -s dotglob globstar
du -sch **/*.o
4
  • There is a bit of a problem with the first one. There is such thing as MAXARGS . So there will be multiple iterations of du , and it will produce multiple total lines. Here's example: paste.ubuntu.com/23092752 Aug 26, 2016 at 10:09
  • @Serg true. I added another option that avoids that.
    – terdon
    Aug 26, 2016 at 10:12
  • Your first shopt globstar example leaves out the -s; I had to use shopt -s globstar similar to your second example.
    – CrazyPyro
    Feb 13, 2020 at 22:58
  • 1
    @CrazyPyro d'oh! Sorry, that was a typo. Thanks for pointing it out. shopt OPTION without an -s or a -u (or other option, see help shopt) just prints the current value of OPTION. You need shopt -s OPTION to turn one on and shopt -u OPTION to turn it off.
    – terdon
    Feb 13, 2020 at 23:28
9

Use -exec flag to run du command with ; ( meaning per each file)

find . -name "*.o" -exec du -b {} \; | awk '{total+=$1}END{print total}' 

Sample output:

$ find . -name "*.txt"  -exec du -b {} \; | awk '{total+=$1}END{print total,"bytes" }'                                     
find: ‘./.cache/gvfs-burn’: Permission denied
find: ‘./.cache/unity’: Permission denied
852690242 bytes

find is recursive - meaning that it walks through all subdirectories. If you just want to get total of all *.o files in the current directory, just do

du -b -c *.o
0
0

with perl:

perl -le 'map { $sum += -s } @ARGV; print $sum' -- *.pdf

Size of all non-hidden PDF files in current directory.

1
  • 1
    OK, but the OP is looking for .o files and they could be in subdirectories. You might also want to add a }{ before print $sum to avoid printing the sum for every iteration. We only want the last one.
    – terdon
    Aug 26, 2016 at 9:49
0

The solution:

find . -name "*.o" | xargs du -sch

fails if there are spaces in the filenames. This can be fixed with:

find . -name "*.o" -print0 | xargs -0 du -sch

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .