diff --git a/reorg-backup.sh b/reorg-backup.sh new file mode 100755 index 0000000..58ba053 --- /dev/null +++ b/reorg-backup.sh @@ -0,0 +1,117 @@ +#!/bin/bash +# reorg-backup.sh — reorganize backup season files into astro-YEAR folders. +# +# Moves files from: +# //Season/MvtN/YYYY-MM-DD_* +# Into: +# /astro-YEAR//Season/MvtN/YYYY-MM-DD_* +# +# Uses season_info.py to determine the correct ASTRO_YEAR from each file's date. +# NEVER deletes anything — only moves files. +# +# Usage: +# ./reorg-backup.sh [--dry-run] +# +# Example: +# ./reorg-backup.sh ~/drives/data2-main --dry-run +# ./reorg-backup.sh ~/drives/data2-main + +set -euo pipefail + +SCRIPT_DIR="$(dirname "$(realpath "$0")")" +source "$SCRIPT_DIR/sky-cam.conf" +export TIMEZONE + +BACKUP_ROOT="" +DRY_RUN=false + +while [[ $# -gt 0 ]]; do + case "$1" in + --dry-run) DRY_RUN=true; shift ;; + -*) echo "Unknown option: $1"; exit 1 ;; + *) BACKUP_ROOT="$1"; shift ;; + esac +done + +if [ -z "$BACKUP_ROOT" ]; then + echo "Usage: $0 [--dry-run]" + echo " e.g. $0 ~/drives/data2-main --dry-run" + exit 1 +fi + +BACKUP_ROOT="$(realpath "$BACKUP_ROOT")" + +$DRY_RUN && echo "DRY RUN — no files will be moved" +echo "Backup root: $BACKUP_ROOT" +echo "" + +moved=0 +skipped=0 +errors=0 + +# Find all mp4 files in Season/MvtN directories (not already in astro-* dirs) +while IFS= read -r -d '' src_file; do + filename="$(basename "$src_file")" + + # Extract date: handles YYYY-MM-DD_ (underscore) prefix + date_str="${filename%%_*}" + if ! [[ "$date_str" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then + echo "SKIP (unrecognised filename): $src_file" + (( skipped++ )) || true + continue + fi + + # Get ASTRO_YEAR for this date + _info="$(python3 "$SCRIPT_DIR/season_info.py" "$date_str" 2>/dev/null)" || { + echo "SKIP (season_info.py failed for $date_str): $filename" + (( skipped++ )) || true + continue + } + eval "$_info" + + # Reconstruct target path: + # /astro-YEAR///Mvt/ + # Source path is: + # ///Mvt/ + rel_path="${src_file#$BACKUP_ROOT/}" # e.g. north/Winter/Mvt1/2025-01-06_... + cam_and_below="${rel_path#*/}" # e.g. Winter/Mvt1/2025-01-06_... (strip cam) + cam_name="${rel_path%%/*}" # e.g. north + + dest_dir="$BACKUP_ROOT/astro-${ASTRO_YEAR}/$cam_name/$(dirname "$cam_and_below")" + dest_file="$dest_dir/$filename" + + if [ "$src_file" = "$dest_file" ]; then + (( skipped++ )) || true + continue + fi + + if [ -f "$dest_file" ]; then + echo "EXISTS — skip: astro-${ASTRO_YEAR}/$cam_name/$cam_and_below" + (( skipped++ )) || true + continue + fi + + echo "MOVE astro-${ASTRO_YEAR}/$cam_name/$cam_and_below" + + if ! $DRY_RUN; then + mkdir -p "$dest_dir" + if mv "$src_file" "$dest_file"; then + (( moved++ )) || true + else + echo " ERROR: mv failed" + (( errors++ )) || true + fi + else + (( moved++ )) || true + fi + +done < <(find "$BACKUP_ROOT" \ + -not -path "*/astro-*" \ + -regextype posix-extended \ + -regex ".*/[A-Z][a-z]+/Mvt[0-9]+/[0-9]{4}-[0-9]{2}-[0-9]{2}_.*\.mp4" \ + -print0 | sort -z) + +echo "" +echo "────────────────────────────────────────" +echo "Moved: $moved Skipped: $skipped Errors: $errors" +$DRY_RUN && echo "(dry run — re-run without --dry-run to move files)"