Script fehlende Serienepisoden ermitteln
Erscheinungsbild
Mit folgendem Script lassen sich fehlende Episoden einer Serie ermitteln. Hierzu wird das lokale Verzeichnis gegen die TheMovieDB API geprüft und abgeglichen. Der TMDB API Key muss unter ~/tmdb.key abgelegt sein.
Es wird zuerst versucht über den aktuellen Verzeichnisnamen sowie ggf. vorhandener tvshow.nfo (inkl. YEAR Element) die Serie zu ermitteln. Sollten mehrere Ergebnisse bei TMDB gefunden werden, erfolgt eine Auswahl:
# Suche mit Ordnernamen; ergibt mehrere Treffer mit manueller ID Abfrage
root@media-cleaner:/mnt/uncleaned/tvshows/How I Met Your Mother# ~/missing_episodes.sh
Serienname: How I Met Your Mother
TMDb Suchergebnisse:
1100: How I Met Your Mother (2005)
85267: How I Met Your Mother (2010)
Bitte die ID der gewünschten Serie eingeben:
# -------------------------------------------------------------------------------------------------
# Suche mit Erscheinungsjahr aus der lokalen tvshow.nfo; ergibt nur einen Treffer
# und wird automatisch ausgewählt
root@media-cleaner:/mnt/uncleaned/tvshows/How I Met Your Mother# ~/missing_episodes.sh
Serienname: How I Met Your Mother
Jahr gefunden: 2005
Ein Ergebnis gefunden, automatisch gewählt: ID 1100
=== Season 1 (22 von 22 Episoden) ===
Ep Titel Status MediaInfo
--------------------------------------------------------------------
1x1 Verliebt, verlobt, versagt ✅ 720 (AVC) (mkv) | de: AC-3 2en: AC-3 6
1x2 Die lila Giraffe ✅ 720 (AVC) (mkv) | de: AC-3 2en: AC-3 6
1x3 Frauen, Flieger, Freiheit ✅ 720 (AVC) (mkv) | de: AC-3 2en: AC-3 6
1x4 Gutes altes Hemd ✅ 720 (AVC) (mkv) | de: AC-3 2en: AC-3 6
1x5 Von Tänzern und Tauben ✅ 720 (AVC) (mkv) | de: AC-3 2en: AC-3 6
1x6 Die Kürbis-Schlampe ✅ 720 (AVC) (mkv) | de: AC-3 2en: AC-3 6
1x7 Kakerlake liebt Maus ✅ 720 (AVC) (mkv) | de: AC-3 2en: AC-3 6
1x8 Das Duell ✅ 720 (AVC) (mkv) | de: AC-3 2en: AC-3 6
1x9 Wohltaten und Untaten ✅ 720 (AVC) (mkv) | de: AC-3 2en: AC-3 6
1x10 Der Ananas-Vorfall ✅ 720 (AVC) (mkv) | de: AC-3 2en: AC-3 6
1x11 Silvesterlaune ✅ 720 (AVC) (mkv) | de: AC-3 2en: AC-3 6
1x12 Hochzeitsgast plus eins ✅ 720 (AVC) (mkv) | de: AC-3 2en: AC-3 6
1x13 Traum und Wirklichkeit ✅ 720 (AVC) (mkv) | de: AC-3 2en: AC-3 6
1x14 Nur nichts überstürzen ✅ 720 (AVC) (mkv) | de: AC-3 2en: AC-3 6
1x15 Spieleabend ✅ 720 (AVC) (mkv) | de: AC-3 2en: AC-3 6
1x16 Maßgeschneidert ✅ 720 (AVC) (mkv) | de: AC-3 2en: AC-3 6
1x17 Leben unter Gorillas ✅ 720 (AVC) (mkv) | de: AC-3 2en: AC-3 6
1x18 Der Anständige ✅ 720 (AVC) (mkv) | de: AC-3 2en: AC-3 6
1x19 Eine nette Nutte ✅ 720 (AVC) (mkv) | de: AC-3 2en: AC-3 6
1x20 Nur zwei Monate ❌
1x21 Das Super-Date ❌
1x22 Letzter Versuch ❌
#!/bin/bash
TMDB_KEY=$(<~/tmdb.key)
CURRENT_PATH=$(pwd)
EXTENSIONS=("mp4" "mkv" "avi" "mov" "flv" "wmv" "m4v" "mpeg" "mpg")
# Serienname oder TMDb-ID
if [[ "$CURRENT_PATH" =~ \{tmdb-([0-9]+)\} ]]; then
TMDB_ID="${BASH_REMATCH[1]}"
echo "TMDb-ID im Ordner gefunden: $TMDB_ID"
else
SERIES_NAME=$(basename "$CURRENT_PATH")
YEAR=""
if [[ -f "tvshow.nfo" ]]; then
YEAR=$(xmllint --xpath 'string(/tvshow/year)' tvshow.nfo 2>/dev/null)
TITLE=$(xmllint --xpath 'string(/tvshow/title)' tvshow.nfo 2>/dev/null)
[[ -n "$TITLE" ]] && SERIES_NAME="$TITLE"
fi
echo "Serienname: $SERIES_NAME"
[[ -n "$YEAR" ]] && echo "Jahr gefunden: $YEAR"
SEARCH_URL="https://api.themoviedb.org/3/search/tv?api_key=$TMDB_KEY&query=$(echo "$SERIES_NAME" | sed 's/ /%20/g')"
[[ -n "$YEAR" ]] && SEARCH_URL+="&first_air_date_year=$YEAR"
TMDB_SEARCH=$(curl -s "$SEARCH_URL")
RESULTS_COUNT=$(echo "$TMDB_SEARCH" | jq '.total_results // 0')
if [[ "$RESULTS_COUNT" -eq 0 ]]; then
echo "❌ Keine Serie gefunden."
exit 1
elif [[ "$RESULTS_COUNT" -eq 1 ]]; then
TMDB_ID=$(echo "$TMDB_SEARCH" | jq -r '.results[0].id')
echo "Ein Ergebnis gefunden, automatisch gewählt: ID $TMDB_ID"
else
echo "TMDb Suchergebnisse:"
echo "$TMDB_SEARCH" | jq -r '.results[] | "\(.id): \(.name) (\(.first_air_date[0:4]))"'
read -rp "Bitte die ID der gewünschten Serie eingeben: " TMDB_ID
fi
fi
# Staffeln holen
SERIES=$(curl -s "https://api.themoviedb.org/3/tv/$TMDB_ID?api_key=$TMDB_KEY&language=de")
SEASONS=$(echo "$SERIES" | jq -c '.seasons[]?')
echo "--------------------------------------"
while IFS= read -r SEASON; do
SEASON_NUM=$(echo "$SEASON" | jq -r '.season_number')
SEASON_NAME="Season $SEASON_NUM"
# Episoden abrufen
SEASON_JSON=$(curl -s "https://api.themoviedb.org/3/tv/$TMDB_ID/season/$SEASON_NUM?api_key=$TMDB_KEY&language=de")
TOTAL_EPS=$(echo "$SEASON_JSON" | jq '.episodes | length // 0')
LOCAL_COUNT=$(find . -type f -iname "*S$(printf "%02d" "$SEASON_NUM")E*.*" | wc -l | tr -d ' ')
echo "=== $SEASON_NAME ($LOCAL_COUNT von $TOTAL_EPS Episoden) ==="
printf "%-7s %-50s %-6s %s\n" "Ep" "Titel" "Status" "MediaInfo"
printf "%s\n" "--------------------------------------------------------------------"
if [[ "$TOTAL_EPS" -eq 0 ]]; then
continue
fi
EPISODES=$(echo "$SEASON_JSON" | jq -c '.episodes[]?')
echo "$EPISODES" | while IFS= read -r EP; do
EP_NUM=$(echo "$EP" | jq -r '.episode_number // 0')
EP_NAME=$(echo "$EP" | jq -r '.name // "Unknown"')
STATUS="❌"
MI=""
# Datei suchen
FILE=""
for ext in "${EXTENSIONS[@]}"; do
MATCH=$(find . -type f -iname "*S$(printf "%02d" "$SEASON_NUM")E$(printf "%02d" "$EP_NUM")*.$ext" | head -n1)
if [[ -n "$MATCH" ]]; then
FILE="$MATCH"
STATUS="✅"
break
fi
done
# MediaInfo kompakt
if [[ -n "$FILE" ]]; then
VID=$(mediainfo --Inform="Video;%Height% (%Format%)" "$FILE" 2>/dev/null)
EXT=$(echo "$FILE" | awk -F. '{print $NF}')
AUDIO_LINES=$(mediainfo --Inform="Audio;%Language%: %Format% %Channel(s)%" "$FILE" 2>/dev/null)
AUDIO=""
if [[ -n "$AUDIO_LINES" ]]; then
while IFS= read -r line; do
LANG=$(echo "$line" | cut -d: -f1)
VAL=$(echo "$line" | cut -d: -f2- | xargs)
AUDIO+="$LANG: $VAL | "
done <<< "$AUDIO_LINES"
AUDIO=${AUDIO::-3}
fi
MI="$VID ($EXT) | $AUDIO"
fi
printf "%-7s %-50s %-6s %s\n" "${SEASON_NUM}x${EP_NUM}" "$EP_NAME" "$STATUS" "$MI"
done
done <<< "$SEASONS"