#!/bin/bash # migrate-seasons.sh — map old-format seasons clips to the new sky-cam directory # structure using season_info.py to correctly categorize each clip by date. # # The old system used different movement-boundary and naming conventions; # this script ignores the old labels and re-classifies every clip by its # YYYY-MM-DD filename prefix, placing it exactly where montage-mvt.sh expects. # # Usage: # ./migrate-seasons.sh [--dry-run] [OLD_ROOT] # # --dry-run print what would happen without creating any links # OLD_ROOT root of old movie archive (default: ~/drives/local-2tb/movies/sunrise) # # Output: symlinks in $MOVIES_DIR////Mvt/ # # After running, trigger any completed movement montages manually: # ./montage-mvt.sh 2026-04-19 east # Spring Mvt1 (just completed) # ./montage-mvt.sh 2026-01-18 east # Winter Mvt1 # ./montage-mvt.sh 2026-02-16 east # Winter Mvt2 # ./montage-mvt.sh 2026-03-19 east # Winter Mvt3 set -euo pipefail SCRIPT_DIR="$(dirname "$(realpath "$0")")" source "$SCRIPT_DIR/sky-cam.conf" DRY_RUN=false OLD_ROOT="$HOME/drives/local-2tb/movies/sunrise" for arg in "$@"; do case "$arg" in --dry-run) DRY_RUN=true ;; *) OLD_ROOT="$arg" ;; esac done CAM="$SUNRISE_CAM" NEW_ROOT="$MOVIES_DIR/$CAM" echo "Old archive : $OLD_ROOT" echo "New root : $NEW_ROOT" echo "Camera : $CAM" $DRY_RUN && echo "(DRY RUN — no files will be created)" echo "" # Counters per movement declare -A LINKED SKIPPED ERRORS link_clip() { local src="$1" dst_dir="$2" key="$3" local dst="$dst_dir/$(basename "$src")" if [ -e "$dst" ]; then SKIPPED["$key"]=$(( ${SKIPPED["$key"]:-0} + 1 )) return fi if $DRY_RUN; then echo " LINK $(basename "$src")" echo " -> $dst" else mkdir -p "$dst_dir" ln -sf "$src" "$dst" fi LINKED["$key"]=$(( ${LINKED["$key"]:-0} + 1 )) } # Search the season subdirectories for old *-final.mp4 clips while IFS= read -r -d '' src; do fname="$(basename "$src")" # Extract YYYY-MM-DD from filename prefix date_str="${fname%%_*}" if [[ ! "$date_str" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then echo "SKIP (no date): $fname" continue fi # Classify by date using the new system's season_info.py if ! info="$(python3 "$SCRIPT_DIR/season_info.py" "$date_str" 2>/dev/null)"; then echo "ERROR: season_info.py failed for $date_str ($fname)" continue fi eval "$info" # SEASON MVT_NUM DAY_OF_MVT DAYS_IN_MVT MVT_START MVT_END ASTRO_YEAR dst_dir="$NEW_ROOT/$ASTRO_YEAR/$SEASON/Mvt$MVT_NUM" key="${ASTRO_YEAR}/${SEASON}/Mvt${MVT_NUM}" $DRY_RUN && printf " %-12s %s Mvt%s Day %s/%s\n" \ "$date_str" "$SEASON" "$MVT_NUM" "$DAY_OF_MVT" "$DAYS_IN_MVT" link_clip "$src" "$dst_dir" "$key" done < <(find \ "$OLD_ROOT/Spring" \ "$OLD_ROOT/Winter" \ "$OLD_ROOT/Autumn" \ -name "*-final.mp4" -print0 2>/dev/null | sort -z) echo "" echo "=== Summary ===" printf "%-35s %8s %8s\n" "Movement" "Linked" "Skipped" printf "%-35s %8s %8s\n" "--------" "------" "-------" # Collect all movement keys from both arrays declare -A ALL_KEYS for k in "${!LINKED[@]}" "${!SKIPPED[@]}"; do ALL_KEYS["$k"]=1; done for key in $(printf '%s\n' "${!ALL_KEYS[@]}" | sort); do linked=${LINKED["$key"]:-0} skipped=${SKIPPED["$key"]:-0} printf "%-35s %8d %8d\n" "$key" "$linked" "$skipped" done echo "" if $DRY_RUN; then echo "Re-run without --dry-run to create the symlinks." echo "Then trigger montages for completed movements:" else echo "Symlinks created. Trigger montages for completed movements:" fi echo " ./montage-mvt.sh 2026-04-19 $CAM # Spring Mvt1 (just completed, 30/31 days)" echo " ./montage-mvt.sh 2026-01-18 $CAM # Winter Mvt1 (~18/29 days)" echo " ./montage-mvt.sh 2026-02-16 $CAM # Winter Mvt2 (~24/29 days)" echo " ./montage-mvt.sh 2026-03-19 $CAM # Winter Mvt3 (~20/31 days)" echo " # Autumn Mvt1/Mvt3 migrated but Mvt2 is absent — year-end join will not fire."