tags:

views:

1796

answers:

8

I'm trying to calculate the total size in bytes of all files (in a directory tree) matching a filename pattern just using the shell. This is what I have so far:

find -name *.undo -exec stat -c%s {} \; | awk '{total += $1} END {print total}'

Is there an easier way to do this? I feel like there should be a simple du or find switch that does this for me but I can't find one.

To be clear I want to total files matching a pattern anywhere under a directory tree which means

du -bs *.undo

won't work because it only matches the files in the current directory.

A: 

Check the du (disk usage) command.

CMS
+1  A: 
du -c *pattern*

This will print the total on the last line of output.

Lieven
And use tail to trim off all but the last line. +1. =]
strager
That'll only find the files that match the pattern in the current directory, though - won't it?
Jonathan Leffler
+3  A: 
find -name '*.undo' -exec wc -c {} + | tail -n 1

should give the actual total number of bytes in the files, if you don't have too many files (where "too many" is going to be a really large number, probably in the thousands). Or if you just want to get the number alone,

find -name '*.undo' -exec wc -c {} + | tail -n 1 | cut -d' ' -f 1
David Zaslavsky
You should quote '*.undo', "*.undo", \*.undo, or similar; otherwise, you'll get wrong results if there exists a.undo file in the current directory.
ephemient
+2  A: 

Python is part of most linux distributions.

import os
import fnmatch
size= 0
for path, dirs, files in os.walk( '.' ):
    for f in files:
        if fnmatch.fnmatch(f,'*.py'):
            fileSize= os.path.getsize( os.path.join(path,f) ) 
            print f, fileSize
            size += fileSize
print size

Longish, but perfectly clear and highly extensible.

S.Lott
+5  A: 

Try:

find . -name "*.undo" -ls | awk '{total += $7} END {print total}'

On my system the size of the file is the seventh field in the find -ls output. If your find ... -ls output is different, adjust.

In this version, using the existing directory information (file size) and the built-in ls feature of find should be efficient, avoiding process creations or file i/o.

Also: this add the directory argument "." and quotes the file name pattern,which the initial answer omitted.

tpgould
That should work, but the -ls option to find, and awk, are overkill for this task.
David Zaslavsky
nope not overkill at all.
vladr
+3  A: 

With zsh, you can use extended globbing to do:

du -c **/*.undo

Chris AtLee
And Fish and Bash 4.0 too!
ephemient
+2  A: 
find -name *.undo -print0 | du -hc --files0-from=-
+1  A: 
find -name *.undo -print0 | du -hc --files0-from=- | tail -n 1

Put together from gerdemb's and strager's contributions. Using du -cb should display bytes.

xilef