LinuxtoolsTested on real hardware

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.

DistrosDebian 12, Ubuntu 24.04
Shellbash
Updated
Script
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/Movies or /srv/media/Shows. This is a placeholder; point it at your real library root.
    • MIN_MINUTES — the runtime below which a file is flagged (default 15). Use a low value like 15 for a Movies library; drop it to 35 for 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.
Reading the output

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
Runtime is a hint, not a verdict

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.