I am looking for a handy one-liner for computing the average file size in a directory.

What I want is:

size of all files / number of files in directory

  • As in the average size of each file in the directory? or the size of the directory? – Drake Clarris Feb 1 '13 at 15:38
  • The average size of a file in a directory – taffer Feb 1 '13 at 15:39

With FreeBSD / Mac OS X find, stat and awk (not exactly a handy one-liner though):

find -x . -type f -maxdepth 1 -exec sh -c 'stat -f '%z' "${@}"' _ '{}' + | 
LC_ALL=C awk -v pwd="${PWD}" '
   BEGIN{ sum=0; count=0; }
   { sum+=$1; ++count; }
        if (count == 0) exit;
        printf ("number of files: %d\n", count); 
        printf ("average file size in B: %.5f\n", sum/count); 
        printf ("average file size in KB: %.5f\n", (sum/count) / 1024); 
        printf ("average file size in MB: %.5f\n", (sum/count) / (1024*1024)); 
        printf ("directory: %s\n", pwd); 
  • Note that in -v var=value, awk will expand ANSI C sequences as \n, \r... While shells do export PWD, so you can use ENVIRON["PWD"] in awk which doesn't have that kind of problem for directories having backslashes in their name. – Stéphane Chazelas Feb 2 '13 at 17:58
  • If you just need the average size in bytes, you can use find . -type f -exec stat -f%z {} +|awk '{s+=$0}END{print s/NR}'. – Lri Apr 29 '14 at 8:55

With GNU find:

find . -type f -printf '%s\n' | awk '{s+=$0}
  END {printf "Count: %u\nAverage size: %.2f\n", NR, s/NR}'

Or for disk usage:

find . -type f -printf '%k\n' | awk '{s+=$0}
  END {printf "Count: %u\nAverage size: %.2f\n", NR, s*1024/NR}'

Note that if there are several hardlinks of the same file in there, that will count its disk usage several time.

The above only counts regular files, not symlinks or directories or other special files. It includes hidden files.

The same with zsh builtins:

zmodload -i zsh/stat
count() {zstat -Hs -- $REPLY; ((size+=$s[size], count++, 0))}
size=0 count=0
print -f "Count: %s\nAverage size: %.2f\n" $count $(($size./count))

A simplistic solution in one line:

ls -Rl -- "$DIR" | awk 'BEGIN{sum=0;count=0};/^-/{sum+=$5;++count};END{print sum/count}'

It has a syntactic cheat in it, only considering ls output lines that begin with '-', which should constitutes data for regular files.


for only files in a directory, ignoring sub directories:

expr $(du -Ss | cut -f1) / $(find /path/to/dir -maxdepth 1 -type f | wc -l)

Or to count all files including files in subdirectories:

expr $(du -s | cut -f1) / $(find /path/to/dir -type f | wc -l)
  • I'd like not to ignore sub directories. – taffer Feb 1 '13 at 15:46
  • nice. Just add -k to du invocation to have the result in 1024bytes (kb) instead of 512bytes (default size of a file chunk). – Olivier Dulac Feb 1 '13 at 16:30
  • 2
    du -s will add up the disk usage (not size) of all the files and directories and other non-regular files, excluding extra hard links to the same file, while find will count all the regular files. Also, filenames with newline characters will be counted several times. du -S is GNU specific. du -s will report sectors or kilobytes depending on the OS. – Stéphane Chazelas Feb 1 '13 at 17:20
  • As usual @StephaneChazelas your knowledge of linux/unix astounds me and shows me how dirty my quick and dirty solutions are. How long have you been using linux/unix? – Drake Clarris Feb 1 '13 at 18:14
  • Answer is horribly wrong and should be deleted. Explained by Stephane. – Acumenus May 16 '14 at 20:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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