Skip to content

Instantly share code, notes, and snippets.

@Rio6
Last active September 7, 2022 01:39
Show Gist options
  • Save Rio6/1c4ae5237451b13bc2be7fa1da1229ce to your computer and use it in GitHub Desktop.
Save Rio6/1c4ae5237451b13bc2be7fa1da1229ce to your computer and use it in GitHub Desktop.
Prune list of backup files to be daily, weekly, monthly, and yearly depending on the backup age.
#!/bin/sh
# usage: prune-backup [-f] files...
# By default the script prints files to be deleted. Use -f to actually delete.
# Assuming the file names have format of %Y-%m-%dT*
# exit on failure, disable glob
set -ef
filter_date() {
format="$1"
match="$2"
op="${3:--eq}"
while read file; do
date="${file##*/}"
date="${date%T*}"
if [ $(date -d "$date" "+$format") "$op" "$match" ]; then
echo "$file"
fi
done
}
if [ "$1" = "-f" ]; then
dry=
else
dry=1
fi
files="$(printf '%s\n' "$@")"
today=$(date -d $(date +%F) +%s)
last_week="$(expr "$today" - 604800)"
last_month="$(expr "$today" - 2592000)" # assume 30 day month
last_year="$(expr "$today" - 31536000)" # assume 365 day year
# finding files to prune by printing the ones to keep on top of file list then
# filter out the duplicates. The filters here are in parallel, in theory
# there's a probability of lines interrupting each other when the line length
# exceeds stdout buffer, but in practice file name sizes are restricted to be
# much smaller than stdout buffer size so it should be fine.
prune=$( (
echo "$files" | filter_date %s "$last_week" -ge; # in the past week
echo "$files" | filter_date %s "$last_month" -ge | filter_date %w 1 -eq; # in the pat month and every monday
echo "$files" | filter_date %s "$last_year" -ge | filter_date %d 1 -eq; # in the pat montyear and first of every month
echo "$files" | filter_date %j 1 -eq; # first of every year
echo "$files"
) | sort | uniq -u)
IFS='
'
if [ "$dry" ]; then
printf '%s\n' $prune
else
rm -fv $prune
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment