#!/usr/bin/env zsh emulate -L zsh export LC_ALL=C AUDIT="$HOME/msd512-audit" JF="$HOME/Library/Application Support/Jellyfin" DST="/Volumes/photos library iCloud" pgrep -f -i jellyfin > /dev/null && { print "FATAL: Jellyfin is running. Quit it first."; exit 1; } [[ -d "$JF" ]] || { print "FATAL: datadir not found: $JF"; exit 1; } [[ -d "$DST/Media/Jellyfin/Movie" && -d "$DST/Media/Jellyfin/TV" ]] || { print "FATAL: migrated media dirs missing. Phase 3/4 incomplete."; exit 1; } BK="$AUDIT/jellyfin-backup-$(date +%Y%m%d-%H%M%S)" ditto "$JF" "$BK" || { print "FATAL: backup failed"; exit 1; } print "backup: $BK ($(du -sh "$BK" | cut -f1))" M="$JF/root/default/Movies/Movie.mblink" T="$JF/root/default/TV/TV1.mblink" for f in "$M" "$T"; do [[ -f "$f" ]] || { print "FATAL: missing $f"; exit 1; }; done print "before: $(cat "$M") | $(cat "$T")" # CRITICAL: no trailing newline, or the library scan fails with a parse error printf '%s' "$DST/Media/Jellyfin/Movie" > "$M" printf '%s' "$DST/Media/Jellyfin/TV" > "$T" print "after: $(cat "$M") | $(cat "$T")" print "byte check (must be 0 newlines):" for f in "$M" "$T"; do printf '%s -> trailing_newlines=%s\n' "${f:t}" "$(tail -c 1 "$f" | od -An -c | tr -d ' ' | grep -c '\\n')"; done grep -rl -i 'MicroSD' "$JF" --include='*.xml' 2>/dev/null | head -20 > "$AUDIT/jf.remaining-refs.txt" find "$JF/data/playlists" -type f 2>/dev/null | head -5 >> "$AUDIT/jf.remaining-refs.txt" print "===== REMAINING MicroSD REFS (xml only, fix by hand) ====="; cat "$AUDIT/jf.remaining-refs.txt"