summaryrefslogtreecommitdiff
path: root/bin/backup-clean
blob: 30d25db3888ae449d380173551af62d556efebee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#!/bin/sh
# backup garbage collector
[ "$USER" = root ] || exec sudo "$0" "$@"

# Durations, in number of seconds.
hd=3600	    # hour duration:  60s * 60
h12=43200   # 12h: hd * 12
dd=86400    # day duration:   hd * 24
wd=604800   # week duration:  dd * 7
md=2592000  # month duration: dd * 30
yd=31557600 # year duration:  dd * 365.25

now=$(date +'%Y%m%d_%H%M%S')

# The following works only for busybox date, not coreutils
# Kept for reference only.
#date2ts() { d=${1%_*} t=${1#*_}; date -d "$d${t%??}" +%s; }

# Convert date to timestamp, using date from GNU coreutils,
# works also with busybox date.
date2ts() {
	t=$1; r=${t#????}; Y=${t%$r}   # Year (with century)
	t=$r; r=${t#??}; m=${t%$r}     # Month
	t=$r; r=${t#??}; d=${t%$r}     # Day
	t=${r#_}; r=${t#??}; H=${t%$r} # Hour
	t=$r; r=${t#??}; M=${t%$r}     # Minute
	S=${t#??}                      # Second
	date -d "$Y-$m-$d $H:$M:$S" +%s
	#date -jf "%Y-%m-%d %H:%M:%S" "$Y-$m-$d $H:$M:$S" +%s  # BSD, MacOS (not tested)
}

ts2date() { date -d "@$1" +'%Y%m%d_%H%M%S'; }

tsn=$(date2ts "$now")

# Minimal retention delay in seconds, according to backup age,
# implemented using POSIX shell arithmetic.
retention_delay() {
	d=$((tsn - $1))
	if [ $((d < h12)) = 1 ]; then
		r=0	# keep all backups in the last 12 hours
	elif [ $((d < dd)) = 1 ]; then
		r=$hd	# keep 1 backup per hour in the last day
	elif [ $((d < wd)) = 1 ]; then
		r=$dd	# keep 1 backup per day in the last week
	elif [ $((d < md)) = 1 ]; then
		r=$wd	# keep 1 backup per week in the last month
	elif [ $((d < yd)) = 1 ]; then
		r=$md	# keep 1 backup per month in the last year
	else
		r=$yd	# keep 1 backup per year in the previous years
	fi
	echo $r
}

dest=/.history
while getopts :d:nv opt; do
	case $opt in
	(d) tsn=$(date2ts "$OPTARG") ;;
	(n) optn=1 ;;
	(v) optv=1 ;;
	(*) echo "Usage: $0 [-nv] [dir]"; exit 1 ;;
	esac
done
shift $((OPTIND - 1))
[ "$1" ] && dest=$1

# Sorted list of backups, most recent first.
lbu=$(ls -rv "$dest")
lasy=${lbu##*
}
for d in $lbu; do
	tsc=$(date2ts "$d")
	if ! [ "$tsp" ]; then
		[ "$optv" ] && echo "keep $dest/$d"
		tsp=$tsc
		continue
	fi
	mrd=$(retention_delay "$tsp")
	dp=$((tsp - tsc))
	#if [ $((dp < mrd)) = 1 ]; then
	if [ "$d" != "last" -a $((dp < mrd)) = 1 ]; then
		[ "$optv" ] && echo "delete $dest/$d"
		[ "$optn" ] || rm -rf "${dest:?}/$d"
	else
		[ "$optv" ] && echo "keep $dest/$d"
		tsp=$tsc
	fi
done