Files
rclone/kosolidierencloud.sh
2026-09-29 12:18:58 +00:00

172 lines
5.3 KiB
Bash

#!/usr/bin/env bash
#
# magenta-konsolidierung.sh
#
# Cloud-Konsolidierung ohne Remote-Skript: laedt nur die noetigen Ordner aus
# der Magentacloud (rclone) herunter, konsolidiert sie lokal und schiebt das
# Ergebnis zurueck. Quellordner werden auf dem Remote erst geloescht, wenn
# das Ergebnis dort liegt.
#
# Ablauf pro Lauf:
# 1. Tagesordner JJJJ-MM-TT-HH des zuletzt abgeschlossenen Monats
# herunterladen -> zu Monatsordner JJJJ-MM konsolidieren -> hochladen
# -> Tagesordner auf dem Remote loeschen.
# 2. Falls Monatsordner aelter als RETAIN_MONTHS sind: diese ebenfalls
# herunterladen -> zu Jahresordner JJJJ konsolidieren -> hochladen
# -> Monatsordner auf dem Remote loeschen.
#
# Nutzung:
# ./magenta-konsolidierung.sh [-n]
# -n = Dry-Run (zeigt nur, was passieren wuerde)
#
set -euo pipefail
REMOTE="magenta:Technik/DPV_Archiv" # rclone-remote:Pfad zum Archiv
WORK="/tmp/magenta-konsolidierung" # lokales Arbeitsverzeichnis
RETAIN_MONTHS=3 # Monatsordner juenger als x Monate bleiben Monatsordner
DRY_RUN=0
LOG_FILE=""
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg"
if [ -n "$LOG_FILE" ]; then echo "$msg" >> "$LOG_FILE"; fi
return 0
}
usage() { echo "Usage: $0 [-n]" >&2; exit 1; }
while getopts "n" opt; do
case "$opt" in
n) DRY_RUN=1 ;;
*) usage ;;
esac
done
rclone_do() {
if [ "$DRY_RUN" -eq 1 ]; then
log "[Dry-Run] rclone $*"
else
log "rclone $*"
rclone "$@"
fi
}
# ---- Hilfsfunktionen -------------------------------------------------------
# zuletzt abgeschlossener Monat als JJJJ-MM
last_closed_month() {
date -d "$(date +%Y-%m-01) -1 day" +%Y-%m
}
# Monatsdifferenz (a - b) zwischen zwei Werten JJJJ-MM, negativ wenn a frueher
month_diff() {
local a="$1" b="$2"
local ay am by bm
ay=${a%%-*}; am=${a##*-}
by=${b%%-*}; bm=${b##*-}
echo $(( (10#$ay * 12 + 10#$am) - (10#$by * 12 + 10#$bm) ))
}
# lokale Konsolidierung: alle Ordner in "$1" (aufsteigend sortiert, aeltester
# zuerst) zu Ordner "$2" zusammenfuehren; spaetere Laeufe ueberschreiben fruehere,
# die aktuellste Version gewinnt also.
merge_local() {
local srcdir="$1" dest="$2"
local first=1 d
mkdir -p "$dest"
for d in "$srcdir"/*; do
[ -d "$d" ] || continue
if [ "$first" -eq 1 ]; then
if [ "$DRY_RUN" -eq 1 ]; then
log "[Dry-Run] mv $d -> $dest (Grundordner)"
else
mv "$d" "$dest"
fi
first=0
else
if [ "$DRY_RUN" -eq 1 ]; then
log "[Dry-Run] merge $d -> $dest"
else
cp -a "$d/." "$dest/"
fi
fi
done
}
# ---- Vorbereitung ----------------------------------------------------------
CLOSED="$(last_closed_month)"
TODAY_MONTH="$(date +%Y-%m)"
if [ "$DRY_RUN" -ne 1 ]; then
rm -rf "$WORK"
mkdir -p "$WORK"
fi
# Remote-Bestand einmal abfragen (nur Verzeichnisnamen)
mapfile -t REMOTE_DIRS < <(rclone lsf "${REMOTE%/}/" --dirs-only 2>/dev/null | sed 's:/$::')
# ---- Stufe 1: Tagesordner des Vormonats -> Monatsordner --------------------
MONTH_SOURCES=()
for d in "${REMOTE_DIRS[@]}"; do
[[ "$d" =~ ^${CLOSED}-[0-9]{2}-[0-9]{2}$ ]] || continue
MONTH_SOURCES+=("$d")
done
if [ ${#MONTH_SOURCES[@]} -gt 0 ]; then
log "Stufe 1: ${#MONTH_SOURCES[@]} Tagesordner fuer Monat $CLOSED konsolidieren"
for d in "${MONTH_SOURCES[@]}"; do
rclone_do copy "${REMOTE%/}/$d" "$WORK/tage/$d"
done
merge_local "$WORK/tage" "$WORK/out/$CLOSED"
# erst Ergebnis hochladen, dann Quellordner auf dem Remote entfernen
rclone_do copy "$WORK/out/$CLOSED" "${REMOTE%/}/$CLOSED"
for d in "${MONTH_SOURCES[@]}"; do
rclone_do purge "${REMOTE%/}/$d"
done
else
log "Stufe 1: keine Tagesordner fuer $CLOSED vorhanden (nichts zu tun)"
fi
# ---- Stufe 2: alte Monatsordner -> Jahresordner ----------------------------
YEAR_FOLDERS=()
for d in "${REMOTE_DIRS[@]}"; do
[[ "$d" =~ ^[0-9]{4}-[0-9]{2}$ ]] || continue
diff=$(month_diff "$d" "$TODAY_MONTH")
if [ "$diff" -ge 0 ] || [ $(( -diff )) -lt "$RETAIN_MONTHS" ]; then
continue # juenger als RETAIN_MONTHS: als Monatsordner stehen lassen
fi
YEAR_FOLDERS+=("$d")
done
if [ ${#YEAR_FOLDERS[@]} -gt 0 ]; then
log "Stufe 2: ${#YEAR_FOLDERS[@]} Monatsordner in Jahresordner konsolidieren"
# aufsteigend sortiert, damit neuere Monatsordner aeltere ueberschreiben
mapfile -t YEAR_FOLDERS < <(printf '%s\n' "${YEAR_FOLDERS[@]}" | sort)
current_year=""
for m in "${YEAR_FOLDERS[@]}"; do
yr="${m:0:4}"
if [ "$yr" != "$current_year" ]; then
current_year="$yr"
mkdir -p "$WORK/monate/$yr"
fi
rclone_do copy "${REMOTE%/}/$m" "$WORK/monate/$yr/$m"
done
# je Jahr konsolidieren, hochladen, dann Quellen auf dem Remote loeschen
for yr in "$WORK/monate"/*; do
[ -d "$yr" ] || continue
y="$(basename "$yr")"
merge_local "$yr" "$WORK/out/$y"
rclone_do copy "$WORK/out/$y" "${REMOTE%/}/$y"
done
for m in "${YEAR_FOLDERS[@]}"; do
rclone_do purge "${REMOTE%/}/$m"
done
else
log "Stufe 2: keine Monatsordner aelter als $RETAIN_MONTHS Monate (nichts zu tun)"
fi
log "Fertig."
[ "$DRY_RUN" -eq 1 ] && log "(Dry-Run: nichts wurde veraendert.)"