Calculate size of files in shell
LinuxShellLinux Problem Overview
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.
Linux Solutions
Solution 1 - Linux
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.
Solution 2 - Linux
With zsh, you can use extended globbing to do:
du -c **/*.undo
Solution 3 - Linux
find -name *.undo -print0 | du -hc --files0-from=-
Solution 4 - Linux
du -c *pattern*
This will print the total on the last line of output.
Solution 5 - Linux
I have been looking at this problem too (only a year later...) - only just found this page.
Something that I found works (for me) is the following:
find /mnt/iso -name *.avi -printf "%s\n" | paste -sd+ - | bc
This will return the total size of all the .avi files in all the sub-folders below /mnt/iso
I have to give credit to radoulov for the paste command - see this page: https://stackoverflow.com/questions/450799/linux-command-to-sum-integers-one-per-line
Just to add - just in case a folder matches the search term - it's a good idea to use -type f
in the find command too.
Solution 6 - Linux
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
Solution 7 - Linux
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.
Solution 8 - Linux
find -name '*.undo' -print0 | du -hc --files0-from=- | tail -n 1
Put together from [gerdemb][1]'s and strager's contributions. Using du -cb
should display bytes.
[1]: https://stackoverflow.com/users/27478/gerdemb "gerdemb"
Solution 9 - Linux
I use du command like this to get the number only:
du file_list | awk '{s+=$1} END {print s}'
Solution 10 - Linux
How about this simple one.
find ./ -name *.undo | xargs wc
Solution 11 - Linux
Or, you can just do this:
dir=$1
for file in $dir/* ; do
length_file=`stat -c %s $file`
echo "File $file has length $length_file"
length_total=`expr $length_total + $length_file`
done
echo "Total length: $length_total ."
Where stat displays a file or file system status. The argument -c means using the specified format instead of the default one, and the format sequence $s allows the display of the total size of bytes.
expr
Just evaluates an expression.
Solution 12 - Linux
Perl one-liner:
find . -name "*.undo" -ls | perl -lane '$t += $F[6]; END{print $t}'
The @F
autosplit array starts at index $F[0]
while awk fields start with $1, hence $F[6]
is used instead of awk's $7
Solution 13 - Linux
du -c
Solution 14 - Linux
I think the version with xargs could be imroved (simplified) ls -1 *.undo | xargs wc
Solution 15 - Linux
Check the du (disk usage) command.