From 079373281d9db7f0dd7fc6a53fcabc773ac95e4c Mon Sep 17 00:00:00 2001 From: David Vazgenovich Shakaryan Date: Mon, 9 Feb 2026 23:03:21 -0800 Subject: use AWK to prefilter and sort input For the two-array deletion loop, it is vital that the output sort order be the reverse of the input sort order. It's unlikely to matter given the generated directory names, but using AWK for both is safer than using `sort' for the input. --- backomp | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/backomp b/backomp index 0580750..c56396e 100755 --- a/backomp +++ b/backomp @@ -2,7 +2,19 @@ set -e -! read -rd '' FILTER_AWK <<'EOF' +! read -rd '' AWK_PREFILTER <<'EOF' +/(\/|^)[0-9]{4}-[0-9]{2}-[0-9]{2}-[0-9]{6}$/ { + a[$0] +} + +END { + n = asorti(a) + for (i = n; i >= 1; --i) + print a[i] +} +EOF + +! read -rd '' AWK_FILTER <<'EOF' function flr(n, s) { return int(n / s) * s } @@ -31,12 +43,16 @@ BEGIN { } NR == 1 { - ++keep[$1] + ++keep[$0] } { - t = mktime(gensub(/(.*\/|^)(.+)-(..)-(..)-(..)(..)(..)/, + t = mktime(gensub(/(.*\/|^)(.+)-(..)-(..)-(..)(..)(..)$/, "\\2 \\3 \\4 \\5 \\6 \\7", 1), 1) + if (t < 0) { + ++keep[$0] + next + } bt["h"] = flr(t, 60*60) bt["d"] = flr(t, 24*60*60) @@ -60,7 +76,7 @@ NR == 1 { next if ((b, bt[b]) in bkeep || ret[b] == "*" || bc[b]++ < ret[b]) - bkeep[b, bt[b]] = $1 + bkeep[b, bt[b]] = $0 for (j in buckets) last[b, buckets[j]] = bt[buckets[j]] @@ -90,19 +106,23 @@ backup() { [[ "$((dcount++))" -ne 0 ]] && echo echo "[${dcount}] [${retain}] ${src_path} => ${dest_dir}" - mapfile -t snaps < <(shopt -s nullglob; - printf '%s\n' "${dest_dir}/"* | sort -r | head -c -1) + mapfile -td $'\0' snaps < <(shopt -s nullglob; + printf '%s\0' "${dest_dir}/"* | awk -v 'RS=\0' -v 'ORS=\0' \ + -- "${AWK_PREFILTER}") dest_path="${dest_dir}/$(date -u '+%Y-%m-%d-%H%M%S')" run rsync -ac --mkpath ${snaps[0]:+"--link-dest=${snaps[0]}"} \ "${src_path}" "${dest_path}" - snaps=("${dest_path}" "${snaps[@]}") + snaps+=("${dest_path}") + mapfile -td $'\0' snaps < <( + printf '%s\0' "${snaps[@]}" | awk -v 'RS=\0' -v 'ORS=\0' \ + -- "${AWK_PREFILTER}") - mapfile -t keep < <( - awk \ + mapfile -td $'\0' keep < <( + printf '%s\0' "${snaps[@]}" | awk -v 'RS=\0' -v 'ORS=\0' \ -v "opt_retain=${retain}" \ -v "opt_week_start=${week_start}" \ - -- "${FILTER_AWK}" < <(printf '%s\n' "${snaps[@]}")) + -- "${AWK_FILTER}") if [[ -z "${keep}" ]]; then echo "WARNING: dirs to keep shouldn't be empty; skipping" >&2 return -- cgit v1.2.3-70-g09d2