28

I am trying to find the total disk space used by files older than 180 days in a particular directory. This is what I'm using:

    find . -mtime +180 -exec du -sh {} \;

but the above is quiet evidently giving me disk space used by every file that is found. I want only the total added disk space used by the files. Can this be done using find and exec command ?

Please note I simply don't want to use a script for this, it will be great if there could be a one liner for this. Any help is highly appreciated.

dig_123
  • 2,240
  • 6
  • 35
  • 59
  • If all your files are likely to fit on one command line, then this will work: `find . -mtime +180 -exec du -ch {} \+ | tail -n1` (note the `\+` which means put all the found filenames as arguments - unless they won't all fit, in which case run the command as few times as poss, maximising the files each time). – artfulrobot Sep 23 '14 at 13:50

5 Answers5

22

Why not this?

find /path/to/search/in -type f -mtime +180 -print0 | du -hc --files0-from - | tail -n 1
gerrit
  • 24,025
  • 17
  • 97
  • 170
user2059857
  • 1,191
  • 13
  • 15
  • 5
    `-type f` helps here as well :) `find /path/to/search/in -type f -mtime +180 -print0 | du -hc --files0-from - | tail -n 1` – ROunofF Mar 15 '16 at 19:51
20

@PeterT is right. Almost all these answers invoke a command (du) for each file, which is very resource intensive and slow and unnecessary. The simplest and fastest way is this:

find . -type f -mtime +356 -printf '%s\n' | awk '{total=total+$1}END{print total/1024}'
k-h
  • 396
  • 1
  • 3
  • 5
16

du wouldn't summarize if you pass a list of files to it.

Instead, pipe the output to cut and let awk sum it up. So you can say:

find . -mtime +180 -exec du -ks {} \; | cut -f1 | awk '{total=total+$1}END{print total/1024}'

Note that the option -h to display the result in human-readable format has been replaced by -k which is equivalent to block size of 1K. The result is presented in MB (see total/1024 above).

devnull
  • 118,548
  • 33
  • 236
  • 227
  • Actually ```du``` will give you the total of a list of files if you pass it the ```-c``` option but there could easily be too many files. – jcoffland May 31 '15 at 01:20
  • 3
    Should add `-type f` otherwise it will include current directory `.` total size to result. – ruuter Jul 08 '15 at 16:53
  • 3
    **This gives incorrect results** without `-type f` as suggested above – ollybee Jul 24 '15 at 11:29
  • 3
    This solution has many flaws, and should be never used: 1) Bug mentioned in other comments 2) It is *very* slow, as it executes du for every single file 3) awk may not be able to handle large enough integers *Please revoke this as accepted answer* and accept the answer by user2059857. – Balázs Pozsár Feb 05 '16 at 12:13
8

Be careful not to take into account the disk usage by the directories. For example, I have a lot of files in my ~/tmp directory:

$ du -sh ~/tmp
3,7G    /home/rpet/tmp

Running the first part of example posted by devnull to find the files modified in the last 24 hours, we can see that awk will sum the whole disk usage of the ~/tmp directory:

$ find ~/tmp -mtime 0 -exec du -ks {} \; | cut -f1
3849848
84
80

But there is only one file modified in that period of time, with very little disk usage:

$ find ~/tmp -mtime 0
/home/rpet/tmp
/home/rpet/tmp/kk
/home/rpet/tmp/kk/test.png

$ du -sh ~/tmp/kk
84K /home/rpet/tmp/kk

So we need to take into account only the files and exclude the directories:

$ find ~/tmp -type f -mtime 0 -exec du -ks {} \; | cut -f1 | awk '{total=total+$1}END{print total/1024}'
0.078125

You can also specify date ranges using the -newermt parameter. For example:

$ find . -type f -newermt "2014-01-01" ! -newermt "2014-06-01"

See http://www.commandlinefu.com/commands/view/8721/find-files-in-a-date-range

Community
  • 1
  • 1
rpet
  • 156
  • 1
  • 6
  • surely `find ... \+` is far more efficient? – artfulrobot Sep 23 '14 at 13:52
  • for me, `find . -type f -newermt "2015-08-08" ! -newermt "2016-09-09" -exec du -ks {} \; | cut -f1 | awk '{total=total+$1}END{print total/1024}'` did the trick, thank you! ;) – Aitor Sep 07 '16 at 10:30
6

You can print file size with find using the -printf option, but you still need awk to sum.

For example, total size of all files older than 365 days:

find . -type f -mtime +356 -printf '%s\n' \
     | awk '{a+=$1;} END {printf "%.1f GB\n", a/2**30;}'
PeterT
  • 920
  • 8
  • 20
  • I actually liked this answer the best. I modified -mtime to -10 for files newer than 10 days, but yours was the easiest to follow. Thanks. – Tensigh Oct 18 '17 at 08:04