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
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
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With