Audit a Media Library for Renamed-Wrong Files
Scan a movie or TV folder with ffprobe, list every file's runtime sorted shortest-first, and flag anything suspiciously short — catching samples, trailers, and mismatched files hiding under the wrong title.
bash#!/usr/bin/env bash
# Audit a media library for renamed-wrong files by runtime.
# A feature film that ffprobe reports as 4 minutes is a trailer or sample
# matched (and often renamed) as the feature. A "20 minute" episode that
# runs 90 is two files concatenated or a wrong match. Sorting by runtime
# makes both jump to the ends of the list.
#
# Read-only: it never renames or deletes anything. You decide what to fix.
set -euo pipefail
# --- make these values your own ---
MEDIA_DIR="${1:-/srv/media/Movies}" # the library folder to audit
MIN_MINUTES="${2:-15}" # flag anything shorter than this
command -v ffprobe >/dev/null || { echo "ffprobe not found — install ffmpeg."; exit 1; }
[ -d "$MEDIA_DIR" ] || { echo "Not a directory: $MEDIA_DIR"; exit 1; }
echo "Auditing: $MEDIA_DIR (flagging < ${MIN_MINUTES} min)"
echo
# Collect "seconds<TAB>path" for every video file, then sort numerically.
find "$MEDIA_DIR" -type f \
\( -iname '*.mkv' -o -iname '*.mp4' -o -iname '*.avi' -o -iname '*.m4v' -o -iname '*.mov' \) -print0 |
while IFS= read -r -d '' f; do
dur=$(ffprobe -v error -show_entries format=duration \
-of default=noprint_wrappers=1:nokey=1 "$f" 2>/dev/null)
# ffprobe returns empty or N/A for unreadable files — surface those too.
if [ -z "$dur" ] || [ "$dur" = "N/A" ]; then dur=0; fi
printf '%.0f\t%s\n' "$dur" "$f"
done | sort -n | while IFS=$'\t' read -r secs path; do
mins=$(( secs / 60 ))
flag=""
[ "$mins" -lt "$MIN_MINUTES" ] && flag=" <-- SHORT, check this"
printf '%4d min %s%s\n' "$mins" "$(basename "$path")" "$flag"
done
What this does
This script walks a media folder, asks ffprobe (the inspection tool that ships with FFmpeg) for each video file’s duration, and prints every file sorted shortest-runtime-first with the minutes shown. Anything below a threshold you set is flagged. It is read-only — it never renames, moves, or deletes a file; it just gives you a ranked list so the wrong matches are obvious.
It exists because of a specific failure mode: when you adopt a messy existing library into Radarr or Sonarr, a file can be matched to the wrong title and renamed to suit — a 4-minute trailer ends up named like the feature, or a sample clip sits in a movie folder. Since the name now looks correct, the only tell left is the runtime. A trailer sorts to the very top of this list; a double-length concatenation sorts to the bottom. Both are worth a look. It pairs with Organizing a Jellyfin Library and the Plex naming guide.
Prerequisites
- FFmpeg installed (provides
ffprobe):sudo apt-get install -y ffmpeg. - Read access to the library folder — run it as a user who can read the media, or over SSH on the server that holds it.
Notes
- Make these values your own. The script takes two optional arguments: the folder to audit and the short-flag threshold in minutes. Both have placeholder defaults you should change:
MEDIA_DIR— the library path, e.g./srv/media/Moviesor/srv/media/Shows. This is a placeholder; point it at your real library root.MIN_MINUTES— the runtime below which a file is flagged (default15). Use a low value like15for a Movies library; drop it to3–5for a Shows library where short episodes are legitimate.- Rule of thumb: if a value looks specific to one machine, it’s a placeholder to change — not a literal to copy.
The list is sorted shortest-first, so scan the top for trailers and samples (absurdly short) and the bottom for wrong-length matches (a “22-minute” sitcom episode that runs 90 minutes is two files joined, or a film in a TV folder). The <-- SHORT marker only fires below your threshold; the sort does the rest of the work.
- It reads container-reported duration, not decoded frames, so it is fast even on a large library — ffprobe reads the header, it does not play the file.
- Usage examples:
# Audit the default folder with the default 15-minute flag
./media-runtime-audit.sh
# Audit a specific Movies library, flag anything under 20 minutes
./media-runtime-audit.sh /srv/media/Movies 20
# Audit a Shows library, only flag truly tiny files (under 3 minutes)
./media-runtime-audit.sh /srv/media/Shows 3
A short runtime flags a file for your review — it doesn’t prove the file is wrong. Featurettes, short films, stand-up specials, and legitimately short anime episodes are all genuinely brief. The script deliberately never touches your files; confirm each flag by eye (or in Jellyfin’s Identify screen) before renaming anything.