Bash script to limit a directory size by deleting files accessed last Bash script to limit a directory size by deleting files accessed last shell shell

Bash script to limit a directory size by deleting files accessed last


I improved brunner314's example and fixed the problems in it.

Here is a working script I'm using:

#!/bin/bashDELETEDIR="$1"MAXSIZE="$2"if [[ -z "$DELETEDIR" || -z "$MAXSIZE" || "$MAXSIZE" -lt 1 ]]; then    echo "usage: $0 [directory] [maxsize in megabytes]" >&2    exit 1fifind "$DELETEDIR" -type f -printf "%T@::%p::%s\n" \| sort -rn \| awk -v maxbytes="$((1024 * 1024 * $MAXSIZE))" -F "::" '  BEGIN { curSize=0; }  {   curSize += $3;  if (curSize > maxbytes) { print $2; }  }  ' \  | tac | awk '{printf "%s\0",$0}' | xargs -0 -r rm# delete empty directoriesfind "$DELETEDIR" -mindepth 1 -depth -type d -empty -exec rmdir "{}" \;


Here's a simple, easy to read and understand method I came up with to do this:

DIRSIZE=$(du -s /PATH/TO/FILES | awk '{print $1}')if [ "$DIRSIZE" -gt "$SOMELIMIT" ]  then    for f in `ls -rt --time=atime /PATH/TO/FILES/*.tar`; do    FILESIZE=`stat -c "%s" $f`    FILESIZE=$(($FILESIZE/1024))    DIRSIZE=$(($DIRSIZE - $FILESIZE))    if [ "$DIRSIZE" -lt "$LIMITSIZE" ]; then        break    fidonefi


I didn't need to use loops, just some careful application of stat and awk. Details and explanation below, first the code:

find /PATH/TO/FILES -name '*.tar' -type f \| sed 's/ /\\ /g' \| xargs stat -f "%a::%z::%N" \| sort -r \| awk '  BEGIN{curSize=0; FS="::"}  {curSize += $2}  curSize > $X_SIZE{print $3}  '| sed 's/ /\\ /g' \| xargs rm

Note that this is one logical command line, but for the sake of sanity I split it up.

It starts with a find command based on the one above, without the parts that limit it to files older than 3 days. It pipes that to sed, to escape any spaces in the file names find returns, then uses xargs to run stat on all the results. The -f "%a::%z::%N" tells stat the format to use, with the time of last access in the first field, the size of the file in the second, and the name of the file in the third. I used '::' to separate the fields because it is easier to deal with spaces in the file names that way. Sort then sorts them on the first field, with -r to reverse the ordering.

Now we have a list of all the files we are interested in, in order from latest accessed to earliest accessed. Then the awk script adds up all the sizes as it goes through the list, and begins outputting them when it gets over $X_SIZE. The files that are not output this way will be the ones kept, the other file names go to sed again to escape any spaces and then to xargs, which runs rm them.