Files
sky-cam/reorg-backup.sh
Claude 507ecf32c8 Fix reorg-backup.sh camera scoping — prevent 2026/ dir misidentified as cam
Restructure find loop to iterate known CAMERAS+sunrise in the main shell
so cam_name is visible in the while body. Previously the for loop ran in
a process substitution subshell, making cam_name unavailable and causing
top-level year dirs (e.g. 2026/) to be treated as camera names.

https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ
2026-04-20 18:49:34 +00:00

118 lines
3.4 KiB
Bash
Executable File

#!/bin/bash
# reorg-backup.sh — reorganize backup season files into astro-YEAR folders.
#
# Moves files from:
# <backup_root>/<cam>/Season/MvtN/YYYY-MM-DD_*
# Into:
# <backup_root>/astro-YEAR/<cam>/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 <backup_root> [--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 <backup_root> [--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
# Iterate over known cameras only — avoids stray season-shaped paths elsewhere
# in the backup (e.g. a top-level 2026/ dir that would be mistaken for a cam).
for cam_name in "${CAMERAS[@]}" sunrise; do
src_root="$BACKUP_ROOT/$cam_name"
[ -d "$src_root" ] || continue
echo "--- $cam_name ---"
while IFS= read -r -d '' src_file; do
filename="$(basename "$src_file")"
# Extract date from YYYY-MM-DD_ prefix
date_str="${filename%%_*}"
if ! [[ "$date_str" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "SKIP (unrecognised filename): $filename"
(( 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"
rel_path="${src_file#$src_root/}" # e.g. Winter/Mvt1/2025-01-06_...
dest_dir="$BACKUP_ROOT/astro-${ASTRO_YEAR}/$cam_name/$(dirname "$rel_path")"
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/$rel_path"
(( skipped++ )) || true
continue
fi
echo "MOVE astro-${ASTRO_YEAR}/$cam_name/$rel_path"
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 "$src_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)
done
echo ""
echo "────────────────────────────────────────"
echo "Moved: $moved Skipped: $skipped Errors: $errors"
$DRY_RUN && echo "(dry run — re-run without --dry-run to move files)"