Server Fault is a question and answer site for system and network administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

We have a set of directories containing lucene indexes. Each index is a mix of different file types (differentiated by extension) eg:


(it's about 10 different extensions)

We'd like to get a total by file extension, eg:

.frq     21234
.fnm     34757

I've tried various combinations of du/awk/xargs but finding it tricky to do exactly this.

share|improve this question
You have the answer for that problem in this post :… – Blueicefield Mar 7 '12 at 13:16
Do you want to know the total size of each type of file or the total number of each type of file ? – Iain Mar 7 '12 at 13:23
Total file size please. – barnybug Mar 7 '12 at 14:11
up vote 11 down vote accepted

For any given extension you an use

find /path -name '*.frq' -exec ls -l {} \; | awk '{ Total += $5} END { print Total }'

to get the total file size for that type.

And after some thinking


ftypes=$(find . -type f | grep -E ".*\.[a-zA-Z0-9]*$" | sed -e 's/.*\(\.[a-zA-Z0-9]*\)$/\1/' | sort | uniq)

for ft in $ftypes
    echo -n "$ft "
    find . -name "*${ft}" -exec ls -l {} \; | awk '{total += $5} END {print total}'

Which will output the size in bytes of each file type found.

share|improve this answer
Thanks, was looking for something that summarized by any extension (as it'd be handy to then sort for example) – barnybug Mar 7 '12 at 14:10
Check my update. – Iain Mar 7 '12 at 14:11
great thanks. awk produces scientific output for some of the numbers, can this be disabled: .fdt 3.15152e+10 – barnybug Mar 7 '12 at 14:15
slightly tweaked to just give plain integer numbers: find . -name "*${ft}" -print0 | xargs -0 du -c | grep total | awk '{print $1}' – barnybug Mar 7 '12 at 14:17
Might want to use -iname to make the file extenstion search case insensitive. – Aaron Copley Mar 7 '12 at 15:16

With bash version4, you just need to call find, ls and awk not necessary:

declare -A ary

while IFS=$'\t' read name size; do 
  ((ary[$ext] += size))
done < <(find . -type f  -printf "%f\t%s\n")

for key in "${!ary[@]}"; do 
  printf "%s\t%s\n" "$key" "${ary[$key]}"
share|improve this answer
thanks for find trick @glenn – Selman Ulug Mar 7 '12 at 16:19
This script doesn't not work well with file names with tab character. Changing read name size to read size name and -printf "%f\t%s\n" to -printf "%s\t%f\n"should fix it. – matt May 25 '15 at 15:36
Note also that this script doesn't work well with files without extension. It will treat whole file name as extension. Add if [ "$name" == "$ext" ]; then ext="*no_extension*"; fi after ext=${name##*.} if you need to prevent it. This will put all files without extension into *no_extension* group (I'm using *no_extension* because * is not a valid character in file name) – matt May 25 '15 at 15:39

Every second column splited by . and last part (extension) saved in array.


find . -type f -printf "%s\t%f\n" | awk '
 split($2, ext, ".")
 e = ext[length(ext)]
 size[e] += $1

 for(i in size)
   print size[i], i
}' | sort -n

then you got every extensions total size in bytes.

60055 gemspec
321991 txt
2075312 html
2745143 rb
13387264 gem
47196526 jar
share|improve this answer

Extending on Iain's script with a faster version for working with a large number of files.


ftypes=$(find . -type f | grep -E ".*\.[a-zA-Z0-9]*$" | sed -e 's/.*\(\.[a-zA-Z0-9]*\)$/\1/' | sort | uniq)

for ft in $ftypes
    echo -ne "$ft\t"
    find . -name "*${ft}" -exec du -bcsh '{}' + | tail -1 | sed 's/\stotal//'
share|improve this answer

This is the solution :

find . -type f | grep -E ".*\.[a-zA-Z0-9]*$" | sed -e 's/.*\(\.[a-zA-Z0-9]*\)$/\1/' | sort | uniq -c | sort -n

Solution posted originally on this post : Get all extensions and their respective file count in a directory

share|improve this answer
This is a count by number of files, not what I was asking - I'd like a total by size. – barnybug Mar 7 '12 at 14:10

I solved using this two commands:

FILES=$(find . -name '*.c')
stat -c %s ${FILES[@]} | awk '{ sum += $1 } END { print ".c" " " sum }'
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.