#!/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.)"