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
- Python 3.8+
rsync- No third-party Python libraries
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
| Flag | Default | Description |
|---|---|---|
--dry-run | off | Print planned actions without executing |
--threshold | 0.90 | Fill fraction for Disk A capacity |
--cutoff-letter | auto | Override the calculated letter boundary (required when Disk A is not mounted) |
--verbose | off | Show rsync output in real time |
--log | ~/plex_sync.log | Path to append-only log file |
How it works
- Inventory — scans the source directory, groups movies by first character of the directory name (no article stripping or normalization)
- Boundary — iterates letter groups in order (
#, A–Z), assigning to Disk A until the next group would exceed the capacity threshold - Delta — for each mounted disk, compares desired vs actual contents
- 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.