From 32b82c7b7d60ac06584cfb236477c9485043dab4 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 20 Apr 2026 14:01:01 +0000 Subject: [PATCH 1/3] Add one-shot migration script for old-format seasons clips MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit migrate-seasons.sh uses season_info.py to re-classify every old *-final.mp4 clip by its YYYY-MM-DD filename prefix, placing a symlink in the correct new-system directory regardless of how the old system labelled movements. Handles the boundary mismatches between old and new movement splits automatically. Coverage after migration (based on available clips): Spring 2026 Mvt1 30/31 days (missing Day 1 only — excellent) Winter Mvt1 ~18/29 days Winter Mvt2 ~24/29 days Winter Mvt3 ~20/31 days Autumn Mvt1 ~24/30 days Autumn Mvt3 ~18/30 days Autumn Mvt2 absent — year-end join will not fire for 2024 cycle https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ --- migrate-seasons.sh | 126 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100755 migrate-seasons.sh diff --git a/migrate-seasons.sh b/migrate-seasons.sh new file mode 100755 index 0000000..cb166a2 --- /dev/null +++ b/migrate-seasons.sh @@ -0,0 +1,126 @@ +#!/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." From 7affbc5c54354ede99dcfd852cdebaf6f6db86f5 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 20 Apr 2026 14:13:12 +0000 Subject: [PATCH 2/3] Revise migrate-seasons.sh: ASTRO_YEAR=2025 only, move not symlink, quarantine bad clips MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Filter to ASTRO_YEAR=2025 (Winter 2025-26 onward); skip Autumn 2025 and earlier - Move files instead of creating symlinks - Quarantine clips matching Dayof92 (Spring clips from broken script with wrong 92-day movement total) to quarantine-old-scripts/ for review + deletion - Preserve clips with Dayof92 (no day number, old legacy format) — these are migrated normally since montage-mvt.sh re-adjusts speed regardless - Summary shows delete commands for temp files and quarantine folder https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ --- migrate-seasons.sh | 151 ++++++++++++++++++++++++++++----------------- 1 file changed, 93 insertions(+), 58 deletions(-) diff --git a/migrate-seasons.sh b/migrate-seasons.sh index cb166a2..f1c3640 100755 --- a/migrate-seasons.sh +++ b/migrate-seasons.sh @@ -1,24 +1,32 @@ #!/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. +# migrate-seasons.sh — move old-format seasons clips into the new sky-cam +# directory structure for astronomical year 2025 only (Winter 2025-26 onward). # -# 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. +# Earlier years (Autumn 2025 / ASTRO_YEAR=2024 and before) are skipped. +# +# Two categories of old file: +# MIGRATE — clips from the legacy script (filename has "Dayof" with no +# preceding digit, e.g. 2026-03-21_Mvt3-Dayof92-final.mp4) +# → moved to the correct $MOVIES_DIR//2025//Mvt/ +# +# QUARANTINE — clips produced by the later broken script that recorded a +# specific day number but used the wrong movement total +# (filename has Dayof92, e.g. 2026-04-10_Mvt1-Day21of92-final.mp4) +# → moved to $MOVIES_DIR//2025/quarantine-old-scripts/ +# Review and delete when you're done: rm -rf # # 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) +# --dry-run print what would happen without moving anything +# 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 +# After running, trigger montages for completed movements: +# ./montage-mvt.sh 2026-04-19 east # Spring Mvt1 (~20/31 days) +# ./montage-mvt.sh 2026-01-18 east # Winter Mvt1 (~18/29 days) +# ./montage-mvt.sh 2026-02-16 east # Winter Mvt2 (~24/29 days) +# ./montage-mvt.sh 2026-03-19 east # Winter Mvt3 (~20/31 days) set -euo pipefail @@ -36,60 +44,76 @@ for arg in "$@"; do done CAM="$SUNRISE_CAM" -NEW_ROOT="$MOVIES_DIR/$CAM" +NEW_ROOT="$MOVIES_DIR/$CAM/2025" +QUARANTINE="$NEW_ROOT/quarantine-old-scripts" -echo "Old archive : $OLD_ROOT" -echo "New root : $NEW_ROOT" -echo "Camera : $CAM" -$DRY_RUN && echo "(DRY RUN — no files will be created)" +echo "Old archive : $OLD_ROOT" +echo "New root : $NEW_ROOT" +echo "Quarantine : $QUARANTINE" +echo "Camera : $CAM" +$DRY_RUN && echo "(DRY RUN — no files will be moved)" echo "" -# Counters per movement -declare -A LINKED SKIPPED ERRORS +declare -A CNT_MIGRATE CNT_QUARANTINE CNT_SKIP -link_clip() { - local src="$1" dst_dir="$2" key="$3" - local dst="$dst_dir/$(basename "$src")" +do_move() { + local src="$1" dst="$2" label="$3" key="$4" + local dst_dir + dst_dir="$(dirname "$dst")" if [ -e "$dst" ]; then - SKIPPED["$key"]=$(( ${SKIPPED["$key"]:-0} + 1 )) + printf " EXISTS %-11s %s\n" "" "$(basename "$src")" + CNT_SKIP["$key"]=$(( ${CNT_SKIP["$key"]:-0} + 1 )) return fi if $DRY_RUN; then - echo " LINK $(basename "$src")" - echo " -> $dst" + printf " %-10s %s\n %13s-> %s/\n" \ + "$label" "$(basename "$src")" "" "$dst_dir" else mkdir -p "$dst_dir" - ln -sf "$src" "$dst" + mv "$src" "$dst" fi - LINKED["$key"]=$(( ${LINKED["$key"]:-0} + 1 )) + case "$label" in + MIGRATE) CNT_MIGRATE["$key"]=$(( ${CNT_MIGRATE["$key"]:-0} + 1 )) ;; + QUARANTINE) CNT_QUARANTINE["$key"]=$(( ${CNT_QUARANTINE["$key"]:-0} + 1 )) ;; + esac +} + +# Returns true if filename has the bad pattern: Dayof92 +# (specific day number + wrong 92-day total from the broken Spring script) +is_quarantine_candidate() { + [[ "$1" =~ Day[0-9]+of92 ]] } -# 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 + # Extract YYYY-MM-DD 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 + # Classify date using the new system's boundaries if ! info="$(python3 "$SCRIPT_DIR/season_info.py" "$date_str" 2>/dev/null)"; then - echo "ERROR: season_info.py failed for $date_str ($fname)" + echo "ERROR: season_info.py failed for $date_str — skipping $fname" continue fi eval "$info" - # SEASON MVT_NUM DAY_OF_MVT DAYS_IN_MVT MVT_START MVT_END ASTRO_YEAR + # Provides: SEASON MVT_NUM DAY_OF_MVT DAYS_IN_MVT ASTRO_YEAR ... - dst_dir="$NEW_ROOT/$ASTRO_YEAR/$SEASON/Mvt$MVT_NUM" - key="${ASTRO_YEAR}/${SEASON}/Mvt${MVT_NUM}" + # Skip everything outside the current astronomical year + if [ "$ASTRO_YEAR" != "2025" ]; then + continue + fi - $DRY_RUN && printf " %-12s %s Mvt%s Day %s/%s\n" \ - "$date_str" "$SEASON" "$MVT_NUM" "$DAY_OF_MVT" "$DAYS_IN_MVT" + key="${SEASON}/Mvt${MVT_NUM}" - link_clip "$src" "$dst_dir" "$key" + if is_quarantine_candidate "$fname"; then + do_move "$src" "$QUARANTINE/$fname" "QUARANTINE" "$key" + else + do_move "$src" "$NEW_ROOT/$SEASON/Mvt$MVT_NUM/$fname" "MIGRATE" "$key" + fi done < <(find \ "$OLD_ROOT/Spring" \ @@ -98,29 +122,40 @@ done < <(find \ -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" "--------" "------" "-------" +echo "=== Summary (ASTRO_YEAR=2025 only) ===" +printf "%-22s %8s %11s %7s\n" "Movement" "Migrated" "Quarantined" "Skipped" +printf "%-22s %8s %11s %7s\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" +for k in "${!CNT_MIGRATE[@]}" "${!CNT_QUARANTINE[@]}" "${!CNT_SKIP[@]}"; do + ALL_KEYS["$k"]=1 done +total_m=0 total_q=0 +for key in $(printf '%s\n' "${!ALL_KEYS[@]}" | sort); do + m=${CNT_MIGRATE["$key"]:-0} + q=${CNT_QUARANTINE["$key"]:-0} + s=${CNT_SKIP["$key"]:-0} + printf "%-22s %8d %11d %7d\n" "$key" "$m" "$q" "$s" + total_m=$(( total_m + m )) + total_q=$(( total_q + q )) +done +printf "%-22s %8d %11d\n" "TOTAL" "$total_m" "$total_q" + 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:" + echo "Re-run without --dry-run to move the files." + echo "" 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." + +echo "Next steps:" +echo " 1. Build montages for completed movements:" +echo " ./montage-mvt.sh 2026-04-19 $CAM # Spring Mvt1" +echo " ./montage-mvt.sh 2026-01-18 $CAM # Winter Mvt1" +echo " ./montage-mvt.sh 2026-02-16 $CAM # Winter Mvt2" +echo " ./montage-mvt.sh 2026-03-19 $CAM # Winter Mvt3" +echo " 2. Confirm each montage plays correctly with music." +echo " 3. Delete temp files from old archive:" +echo " find $OLD_ROOT -name '*-temp.mp4' -delete" +echo " 4. Delete quarantined bad clips once confirmed:" +echo " rm -rf $QUARANTINE" From 331bce38c4d2f522b333281862abb65dc77c960d Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 20 Apr 2026 14:16:13 +0000 Subject: [PATCH 3/3] Simplify migrate-seasons.sh: migrate all clips, drop quarantine logic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All *-final.mp4 clips are valid footage regardless of what speed factor the old script used — montage-mvt.sh re-adjusts the full concatenated video to match music duration anyway, so per-clip speed is irrelevant. Move every ASTRO_YEAR=2025 clip to the correct new movement directory based on its date. Spring Mvt1 now gets all 30 clips (Mar 21–Apr 19). https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ --- migrate-seasons.sh | 105 +++++++++++++++------------------------------ 1 file changed, 35 insertions(+), 70 deletions(-) diff --git a/migrate-seasons.sh b/migrate-seasons.sh index f1c3640..8328498 100755 --- a/migrate-seasons.sh +++ b/migrate-seasons.sh @@ -2,19 +2,13 @@ # migrate-seasons.sh — move old-format seasons clips into the new sky-cam # directory structure for astronomical year 2025 only (Winter 2025-26 onward). # +# Every *-final.mp4 clip is placed in the correct movement directory based on +# its YYYY-MM-DD filename date, regardless of how the old script labelled it. +# montage-mvt.sh re-adjusts speed for the whole movement anyway, so per-clip +# speed accuracy doesn't matter. +# # Earlier years (Autumn 2025 / ASTRO_YEAR=2024 and before) are skipped. # -# Two categories of old file: -# MIGRATE — clips from the legacy script (filename has "Dayof" with no -# preceding digit, e.g. 2026-03-21_Mvt3-Dayof92-final.mp4) -# → moved to the correct $MOVIES_DIR//2025//Mvt/ -# -# QUARANTINE — clips produced by the later broken script that recorded a -# specific day number but used the wrong movement total -# (filename has Dayof92, e.g. 2026-04-10_Mvt1-Day21of92-final.mp4) -# → moved to $MOVIES_DIR//2025/quarantine-old-scripts/ -# Review and delete when you're done: rm -rf -# # Usage: # ./migrate-seasons.sh [--dry-run] [OLD_ROOT] # @@ -23,7 +17,7 @@ # (default: ~/drives/local-2tb/movies/sunrise) # # After running, trigger montages for completed movements: -# ./montage-mvt.sh 2026-04-19 east # Spring Mvt1 (~20/31 days) +# ./montage-mvt.sh 2026-04-19 east # Spring Mvt1 (~30/31 days) # ./montage-mvt.sh 2026-01-18 east # Winter Mvt1 (~18/29 days) # ./montage-mvt.sh 2026-02-16 east # Winter Mvt2 (~24/29 days) # ./montage-mvt.sh 2026-03-19 east # Winter Mvt3 (~20/31 days) @@ -45,44 +39,14 @@ done CAM="$SUNRISE_CAM" NEW_ROOT="$MOVIES_DIR/$CAM/2025" -QUARANTINE="$NEW_ROOT/quarantine-old-scripts" -echo "Old archive : $OLD_ROOT" -echo "New root : $NEW_ROOT" -echo "Quarantine : $QUARANTINE" -echo "Camera : $CAM" +echo "Old archive : $OLD_ROOT" +echo "New root : $NEW_ROOT" +echo "Camera : $CAM" $DRY_RUN && echo "(DRY RUN — no files will be moved)" echo "" -declare -A CNT_MIGRATE CNT_QUARANTINE CNT_SKIP - -do_move() { - local src="$1" dst="$2" label="$3" key="$4" - local dst_dir - dst_dir="$(dirname "$dst")" - if [ -e "$dst" ]; then - printf " EXISTS %-11s %s\n" "" "$(basename "$src")" - CNT_SKIP["$key"]=$(( ${CNT_SKIP["$key"]:-0} + 1 )) - return - fi - if $DRY_RUN; then - printf " %-10s %s\n %13s-> %s/\n" \ - "$label" "$(basename "$src")" "" "$dst_dir" - else - mkdir -p "$dst_dir" - mv "$src" "$dst" - fi - case "$label" in - MIGRATE) CNT_MIGRATE["$key"]=$(( ${CNT_MIGRATE["$key"]:-0} + 1 )) ;; - QUARANTINE) CNT_QUARANTINE["$key"]=$(( ${CNT_QUARANTINE["$key"]:-0} + 1 )) ;; - esac -} - -# Returns true if filename has the bad pattern: Dayof92 -# (specific day number + wrong 92-day total from the broken Spring script) -is_quarantine_candidate() { - [[ "$1" =~ Day[0-9]+of92 ]] -} +declare -A CNT_MOVED CNT_SKIP while IFS= read -r -d '' src; do fname="$(basename "$src")" @@ -102,19 +66,29 @@ while IFS= read -r -d '' src; do eval "$info" # Provides: SEASON MVT_NUM DAY_OF_MVT DAYS_IN_MVT ASTRO_YEAR ... - # Skip everything outside the current astronomical year + # Only process the current astronomical year if [ "$ASTRO_YEAR" != "2025" ]; then continue fi key="${SEASON}/Mvt${MVT_NUM}" + dst="$NEW_ROOT/$SEASON/Mvt$MVT_NUM/$fname" - if is_quarantine_candidate "$fname"; then - do_move "$src" "$QUARANTINE/$fname" "QUARANTINE" "$key" - else - do_move "$src" "$NEW_ROOT/$SEASON/Mvt$MVT_NUM/$fname" "MIGRATE" "$key" + if [ -e "$dst" ]; then + printf " EXISTS %s\n" "$fname" + CNT_SKIP["$key"]=$(( ${CNT_SKIP["$key"]:-0} + 1 )) + continue fi + if $DRY_RUN; then + printf " Day %2s/%-2s %s -> %s/Mvt%s/\n" \ + "$DAY_OF_MVT" "$DAYS_IN_MVT" "$fname" "$SEASON" "$MVT_NUM" + else + mkdir -p "$(dirname "$dst")" + mv "$src" "$dst" + fi + CNT_MOVED["$key"]=$(( ${CNT_MOVED["$key"]:-0} + 1 )) + done < <(find \ "$OLD_ROOT/Spring" \ "$OLD_ROOT/Winter" \ @@ -123,30 +97,23 @@ done < <(find \ echo "" echo "=== Summary (ASTRO_YEAR=2025 only) ===" -printf "%-22s %8s %11s %7s\n" "Movement" "Migrated" "Quarantined" "Skipped" -printf "%-22s %8s %11s %7s\n" "--------" "--------" "-----------" "-------" +printf "%-22s %6s %7s\n" "Movement" "Moved" "Skipped" +printf "%-22s %6s %7s\n" "--------" "-----" "-------" declare -A ALL_KEYS -for k in "${!CNT_MIGRATE[@]}" "${!CNT_QUARANTINE[@]}" "${!CNT_SKIP[@]}"; do - ALL_KEYS["$k"]=1 -done +for k in "${!CNT_MOVED[@]}" "${!CNT_SKIP[@]}"; do ALL_KEYS["$k"]=1; done -total_m=0 total_q=0 +total=0 for key in $(printf '%s\n' "${!ALL_KEYS[@]}" | sort); do - m=${CNT_MIGRATE["$key"]:-0} - q=${CNT_QUARANTINE["$key"]:-0} + m=${CNT_MOVED["$key"]:-0} s=${CNT_SKIP["$key"]:-0} - printf "%-22s %8d %11d %7d\n" "$key" "$m" "$q" "$s" - total_m=$(( total_m + m )) - total_q=$(( total_q + q )) + printf "%-22s %6d %7d\n" "$key" "$m" "$s" + total=$(( total + m )) done -printf "%-22s %8d %11d\n" "TOTAL" "$total_m" "$total_q" +printf "%-22s %6d\n" "TOTAL" "$total" echo "" -if $DRY_RUN; then - echo "Re-run without --dry-run to move the files." - echo "" -fi +$DRY_RUN && echo "Re-run without --dry-run to move the files." && echo "" echo "Next steps:" echo " 1. Build montages for completed movements:" @@ -156,6 +123,4 @@ echo " ./montage-mvt.sh 2026-02-16 $CAM # Winter Mvt2" echo " ./montage-mvt.sh 2026-03-19 $CAM # Winter Mvt3" echo " 2. Confirm each montage plays correctly with music." echo " 3. Delete temp files from old archive:" -echo " find $OLD_ROOT -name '*-temp.mp4' -delete" -echo " 4. Delete quarantined bad clips once confirmed:" -echo " rm -rf $QUARANTINE" +echo " find \"$OLD_ROOT\" -name '*-temp.mp4' -delete"