Here’s a simple script I put together to rotate backup files in a given directory with decreasing resolution the further away we get from the current time.
#!/bin/bash
set -euo pipefail
DRYRUN=${DRYRUN:-1}
DIR=${DIR:-'/backups/mysql'}
HOURS=${HOURS:-48}
DAYS=${DAYS:-35}
MONTHS=${MONTHS:-24}
usage() {
echo "usage: DRYRUN=0 DIR=/backups HOURS=48 DAYS=30 MONTHS=24 $0"
exit 1
}
if [ $DRYRUN -eq 1 ]; then
echo "DRYRUN: No changes will be made"
fi
if [ "$HOURS" -lt 0 ] || [ "$DAYS" -lt 1 ] || [ "$MONTHS" -lt 1 ]; then
echo "ERROR: Cannot have negative rotation"
usage
fi
## Bail and cleanup if we exit early
cleanup() {
find $DIR -type f -execdir rename 's/.process$//g' '{}' \;
}
trap cleanup EXIT
trap cleanup SIGINT
## Flag all the files for processing
find $DIR -type f | grep -v '.process$' | xargs -I{} mv {}{,.process}
while [ $MONTHS -gt 0 ]; do
MONTHS=$(($MONTHS-1))
days=$(( ( $(date '+%s') - $(date -d "$MONTHS months ago" '+%s') ) / 86400 ))
file=$(find $DIR -type f -mtime "+$days" | sort -n | tail -n1)
if [ "$DRYRUN" -eq 0 ]; then
rename 's/.process$//g' "$file"
else
echo "MONTH: $MONTHS $file" | sed 's/.process$//'
fi
done
while [ $DAYS -gt 0 ]; do
DAYS=$(($DAYS-1))
file=$(find $DIR -type f -mtime "+$DAYS" | sort -n | tail -n1)
if [ "$DRYRUN" -eq 0 ]; then
rename 's/.process$//g' "$file"
else
echo "DAY: $DAYS $file" | sed 's/.process$//'
fi
done
while [ $HOURS -gt 0 ]; do
HOURS=$(($HOURS-1))
minutes=$(($HOURS*60))
file=$(find $DIR -type f -mmin "+$minutes" | sort -n | tail -n1)
if [ "$DRYRUN" -eq 0 ]; then
rename 's/.process$//g' "$file"
else
echo "HOUR: $HOURS $file" | sed 's/.process$//'
fi
done
## Delete all remaining files
[ "$DRYRUN" -eq 0 ] && rm "$DIR"/*.process 2> /dev/null