copyarr

Syncs a Plex movie library across two external USB drives using an alphabetical letter boundary. Disk A holds movies whose names start with letters up to a calculated cutoff; Disk B holds the rest. Each disk is independent — the script operates on whichever disk(s) are currently mounted.

Requirements

Usage

python3 plex_sync.py <source> <disk_a> <disk_b> [options]

Example

# Dry run to preview what would happen
python3 plex_sync.py --dry-run \
  /mnt/DriveA/hms-docker/media_data/_library/Movies \
  /mnt/backup_a/Movies \
  /mnt/backup_b/Movies

# Live sync
python3 plex_sync.py \
  /mnt/DriveA/hms-docker/media_data/_library/Movies \
  /mnt/backup_a/Movies \
  /mnt/backup_b/Movies

# When Disk A isn't mounted, specify the cutoff manually
python3 plex_sync.py --cutoff-letter S \
  /mnt/DriveA/hms-docker/media_data/_library/Movies \
  /mnt/backup_a/Movies \
  /mnt/backup_b/Movies

Options

FlagDefaultDescription
--dry-runoffPrint planned actions without executing
--threshold0.90Fill fraction for Disk A capacity
--cutoff-letterautoOverride the calculated letter boundary (required when Disk A is not mounted)
--verboseoffShow rsync output in real time
--log~/plex_sync.logPath to append-only log file

How it works

  1. Inventory — scans the source directory, groups movies by first character of the directory name (no article stripping or normalization)
  2. Boundary — iterates letter groups in order (#, A–Z), assigning to Disk A until the next group would exceed the capacity threshold
  3. Delta — for each mounted disk, compares desired vs actual contents
  4. Sync — deletes stale directories first (letters that shifted), then rsyncs all desired movies from source

Movies starting with digits or symbols are grouped under # and always sort first.

Mount setup

Mount backup drives by label in /etc/fstab for consistent mount points:

LABEL=media_backup    /mnt/backup_a  ext4  defaults,nofail,x-systemd.device-timeout=5  0  2
LABEL=media_backup_b  /mnt/backup_b  ext4  defaults,nofail,x-systemd.device-timeout=5  0  2

The nofail flag prevents boot hangs when a drive isn’t plugged in.