konsolidieren.sh hinzugefügt
This commit is contained in:
146
konsolidieren.sh
Normal file
146
konsolidieren.sh
Normal file
@ -0,0 +1,146 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# konsolidierung.sh
|
||||
#
|
||||
# Konsolidiert die Archiv-Ordner eines rsync/rclone-Archivs:
|
||||
#
|
||||
# Struktur im Archiv: JJJJ-MM-TT-HH/ (z. B. 2026-08-03-14)
|
||||
#
|
||||
# 1. Alle Tages-Ordner eines *abgelaufenen* Monats werden zu einem
|
||||
# Monatsordner JJJJ-MM zusammengefasst. Dabei gewinnt immer die
|
||||
# aktuellste Version einer Datei (der spaetere Lauf ueberschreibt
|
||||
# den frueheren). Der aktuelle Monat bleibt unangetastet.
|
||||
# 2. Monatsordner, die aelter als RETAIN_MONTHS Monate sind, werden
|
||||
# zu einem Jahresordner JJJJ zusammengefasst (gleiche Regel:
|
||||
# neuere Version gewinnt).
|
||||
#
|
||||
# Nutzung:
|
||||
# ./konsolidierung.sh [-n] /pfad/zum/archiv
|
||||
# -n = Dry-Run (zeigt nur, was passieren wuerde)
|
||||
#
|
||||
set -euo pipefail
|
||||
|
||||
DRY_RUN=0
|
||||
RETAIN_MONTHS=3 # Monatsordner juenger als x Monate bleiben Monatsordner
|
||||
LOG_FILE="" # optional: z. B. LOG_FILE=archiv.log setzen
|
||||
|
||||
# Log-Ausgabe: mit Zeitstempel auf Terminal und (falls gesetzt) ins Logfile.
|
||||
log() {
|
||||
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
|
||||
echo "$msg"
|
||||
[ -n "$LOG_FILE" ] && echo "$msg" >> "$LOG_FILE"
|
||||
}
|
||||
|
||||
usage() { echo "Usage: $0 [-n] <archiv-verzeichnis>" >&2; exit 1; }
|
||||
|
||||
while getopts "n" opt; do
|
||||
case "$opt" in
|
||||
n) DRY_RUN=1 ;;
|
||||
*) usage ;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
ARCHIVE="${1:-}"
|
||||
[ -d "$ARCHIVE" ] || { echo "Fehler: Archiv-Verzeichnis '$ARCHIVE' nicht gefunden." >&2; usage; }
|
||||
ARCHIVE="$(cd "$ARCHIVE" && pwd)"
|
||||
|
||||
# ---- Hilfsfunktionen -------------------------------------------------------
|
||||
|
||||
# Letzter abgeschlossener Monat als JJJJ-MM.
|
||||
last_closed_month() {
|
||||
date -d "$(date +%Y-%m-01) -1 day" +%Y-%m
|
||||
}
|
||||
|
||||
# Monatsdifferenz zwischen zwei Werten JJJJ-MM (a - b), 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) ))
|
||||
}
|
||||
|
||||
# Fuehrt alle Quellordner (aufsteigend sortiert, aeltester zuerst) nach DEST
|
||||
# zusammen. Spaetere Laeufe ueberschreiben fruehere => aktuellste Version bleibt.
|
||||
merge_into() {
|
||||
local dest="$1"; shift
|
||||
local src
|
||||
for src in "$@"; do
|
||||
if [ "$DRY_RUN" -eq 1 ]; then
|
||||
log "merge: $src -> $dest (loesche danach: $src)"
|
||||
else
|
||||
log "merge: $src -> $dest"
|
||||
mkdir -p "$dest"
|
||||
cp -a "$src/." "$dest/"
|
||||
rm -rf "$src"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# ---- 1. Tagesordner (JJJJ-MM-TT-HH) zu Monatsordnern (JJJJ-MM) ------------
|
||||
|
||||
TODAY_MONTH="$(date +%Y-%m)"
|
||||
CLOSED="$(last_closed_month)"
|
||||
|
||||
declare -A MONTH_FOLDERS=()
|
||||
for d in "$ARCHIVE"/*; do
|
||||
[ -d "$d" ] || continue
|
||||
base="$(basename "$d")"
|
||||
# exakt JJJJ-MM-TT-HH (4-2-2-2 Ziffern)
|
||||
[[ "$base" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}-[0-9]{2}$ ]] || continue
|
||||
month="${base:0:7}"
|
||||
if [[ "$month" > "$CLOSED" ]]; then
|
||||
continue # aktueller Monat / Zukunft: nicht anfassen
|
||||
fi
|
||||
MONTH_FOLDERS["$month"]+="$d"$'\n'
|
||||
done
|
||||
|
||||
# pro Monat: aelteste zuerst mergen, neueste gewinnt
|
||||
for month in "${!MONTH_FOLDERS[@]}"; do
|
||||
mapfile -t sources < <(sort <<< "${MONTH_FOLDERS[$month]}" | grep -v '^$')
|
||||
dest="$ARCHIVE/$month"
|
||||
if [ -e "$dest" ]; then
|
||||
# Monatsordner existiert schon (Rest vom letzten Lauf?) -> einfach dazumergen
|
||||
merge_into "$dest" "${sources[@]}"
|
||||
else
|
||||
# ersten (aeltesten) Ordner umbenennen, Rest dazumergen
|
||||
first="${sources[0]}"
|
||||
if [ "$DRY_RUN" -eq 1 ]; then
|
||||
log "mv: $first -> $dest"
|
||||
merge_into "$dest" "${sources[@]:1}"
|
||||
else
|
||||
log "mv: $first -> $dest (Grundordner fuer $month)"
|
||||
mv "$first" "$dest"
|
||||
merge_into "$dest" "${sources[@]:1}"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# ---- 2. Alte Monatsordner (JJJJ-MM) zu Jahresordnern (JJJJ) ---------------
|
||||
|
||||
YEAR_FOLDERS=()
|
||||
for d in "$ARCHIVE"/*; do
|
||||
[ -d "$d" ] || continue
|
||||
base="$(basename "$d")"
|
||||
[[ "$base" =~ ^[0-9]{4}-[0-9]{2}$ ]] || continue
|
||||
diff=$(month_diff "${base:0:7}" "$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
|
||||
# aelteste zuerst, damit neuere Monatsversionen ueberschreiben
|
||||
mapfile -t YEAR_FOLDERS < <(printf '%s\n' "${YEAR_FOLDERS[@]}" | sort)
|
||||
current_year=""
|
||||
for d in "${YEAR_FOLDERS[@]}"; do
|
||||
yr="$(basename "$d" | cut -c1-4)"
|
||||
dest="$ARCHIVE/$yr"
|
||||
merge_into "$dest" "$d"
|
||||
done
|
||||
fi
|
||||
|
||||
echo "Fertig."
|
||||
[ "$DRY_RUN" -eq 1 ] && echo "(Dry-Run: nichts wurde veraendert.)"
|
||||
Reference in New Issue
Block a user