Skip to main content

Remove movie folders that have no video files (safely)

Over time a movie library collects folders that hold only posters, .nfo files or subtitles, because the movie itself was deleted or moved. This finds them, shows the list, and deletes only after you confirm.

The logic

A folder is a candidate when nothing under it is a video file. Never include the library root itself (-mindepth 1).

#!/bin/bash
set -euo pipefail
root=${1:?usage: clean-empty-movies <library> [--delete]}
has_video() {
  find "$1" -type f \( -iname '*.mkv' -o -iname '*.mp4' -o -iname '*.m4v' -o -iname '*.avi' -o -iname '*.wmv' \) \
       -print -quit | grep -q .
}
mapfile -d '' dirs < <(find "$root" -mindepth 1 -depth -type d -print0)
todo=()
for d in "${dirs[@]}"; do
  has_video "$d" || todo+=("$d")
done
printf '%s\n' "${todo[@]}"
[[ ${2:-} == --delete ]] || { echo "Dry run. Re-run with --delete."; exit 0; }
read -rp "Delete ${#todo[@]} folders? (y/N) " a
[[ $a == [yY] ]] || exit 0
for d in "${todo[@]}"; do rm -rf -- "$d"; done

Key points

  • Get the test the right way round. has_video returns success (0) when a folder has video, and you delete when it does not. If you invert this by mistake, the list holds every real movie folder. That's why the script defaults to a dry run; always read the list.
  • -print -quit stops at the first video found, which is fast on big libraries.
  • Subtitle-only folders (.srt) count as "no video" here. Adjust the pattern if you keep stray subtitles on purpose.
  • Rescan the library in Plex or Jellyfin afterwards.