Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bash script to keep deleting files until directory size is less than X

Tags:

bash

debian

I'm trying to write a script to keep deleting files from a folder (/home/folder) until the home directory (/home/) size is less than X GB. The script should delete 25 files at a time and these should be the oldest in the directory. However, I'm a noob and I couldn't come up with a loop of sorts. Instead, I wrote several times the same script lines below; it works but I would like to have a loop better. Could you help me out with a more elegant, efficient way?

size=$(du -shb /home/ | awk '{print $1}')
if [ "$size" -gt X ]; then
find /home/folder -maxdepth 1 -type f -printf '%T@\t%p\n' | sort -r | tail -n 25 | sed 's/[0-9]*\.[0-9]*\t//' | xargs -d '\n' rm -f
sleep 30
else
exit
fi
like image 223
user3526613 Avatar asked Mar 19 '23 15:03

user3526613


2 Answers

Not bad! The simplest way of making it loop is simply to add an infinite loop around it. Your exit statement will exit the script and obviously therefore also the loop:

while true
do
  size=$(du -shb /home/ | awk '{print $1}')
  if [ "$size" -gt X ]; then
    find /home/folder -maxdepth 1 -type f -printf '%T@\t%p\n' | sort -r | tail -n 25 | sed     's/[0-9]*\.[0-9]*\t//' | xargs -d '\n' rm -f
    sleep 30
  else
    exit  # <- Loop/script exits here
  fi
done

You can also rewrite the logic to make it prettier:

while [ "$(du -shb /home/ | awk '{print $1}')" -gt X ]
do
  find /home/folder -maxdepth 1 -type f -printf '%T@\t%p\n' | \
      sort -n | head -n 25 | cut -d $'\t' -f 2-  | xargs -d '\n' rm -f
done

And you can also rewrite it into not iterating /home over and over, thereby allowing you to delete single files instead of blocks of 25:

usage=$(du -sb /home | cut -d $'\t' -f 1)
max=1000000000
if (( usage > max ))
then
  find /home/folder -maxdepth 1 -type f -printf '%T@\t%s\t%p\n' | sort -n | \
    while (( usage > max )) && IFS=$'\t' read timestamp size file
    do
      rm -- "$file" && (( usage -= size ))
    done
fi
like image 195
that other guy Avatar answered Apr 25 '23 09:04

that other guy


If you are looking for a BusyBox compatible script:

DIRECTORY=$1
MAX_SIZE_MB=$2
KB_TO_MB=1000
MAX_SIZE_KB=$(($MAX_SIZE_MB*$KB_TO_MB))

if [ ! -d "$DIRECTORY" ]
then
  echo "Invalid Directory: $DIRECTORY"
  exit 1
fi

usage=$(du -s $DIRECTORY | awk '{print $1}')
echo "$DIRECTORY - $(($usage/$KB_TO_MB))/$MAX_SIZE_MB MB Used"
if (( usage > $MAX_SIZE_KB ))
then
    #https://stackoverflow.com/questions/1447809/awk-print-9-the-last-ls-l-column-including-any-spaces-in-the-file-name
    files=($(find $DIRECTORY -maxdepth 1 -type f -print| xargs ls -lrt | sed -E -e 's/^([^ ]+ +){8}//'))
    for file in ${files[@]};
    do
        size=$(du -s "$file" | awk '{print $1}')
        rm -f "$file"
        ((usage -= size))
        if (( $usage < $MAX_SIZE_KB ))
        then
           break
        fi  
    done
fi
like image 28
TheoretiCAL Avatar answered Apr 25 '23 07:04

TheoretiCAL