Ein Uploader für Nextcloud, der Bilder und Videos nach Datum in einen Ordner auf einer Nextcloud überträgt.
Find a file
2026-06-23 21:15:20 +02:00
docs Use XDG user configuration path 2026-06-23 21:15:20 +02:00
src/nextcloud_uploader Use XDG user configuration path 2026-06-23 21:15:20 +02:00
tests Use XDG user configuration path 2026-06-23 21:15:20 +02:00
.gitignore feat: add stateless Nextcloud media uploader 2026-06-21 23:10:46 +02:00
config.example.yaml feat: add stateless Nextcloud media uploader 2026-06-21 23:10:46 +02:00
pyproject.toml feat: add stateless Nextcloud media uploader 2026-06-21 23:10:46 +02:00
README.md Use XDG user configuration path 2026-06-23 21:15:20 +02:00

Nextcloud Media Uploader

Ein stateless CLI-Uploader für Bilder und Videos. Dateien aus einem gemeinsamen lokalen Ordner werden anhand ihres Aufnahmedatums nach folgendem Muster in Nextcloud abgelegt:

/Bilder/Fotos/2026/06/IMG_20260620_120052125.jpg
/Bilder/Fotos/2026/06/VID_20260621_105904.mp4

Nach einem bestätigten Upload wird die lokale Datei gelöscht. Es gibt keine SQLite-Datenbank; Nextcloud ist die einzige Quelle der Wahrheit.

Eine vollständige Beschreibung von Installation, Konfiguration, internem Ablauf, Fehlerbehandlung sowie Cron- und systemd-Betrieb enthält das ausführliche Benutzer- und Betriebshandbuch.

Voraussetzungen

  • Python 3.11 oder neuer
  • ExifTool (sudo apt install libimage-exiftool-perl unter Debian/Ubuntu)
  • Ein Nextcloud-App-Passwort
  • Ein gültiges, vom System akzeptiertes HTTPS-Zertifikat

Installation

python3 -m venv .venv
. .venv/bin/activate
pip install -e .
mkdir -p ~/.config/nextcloud-uploader
cp config.example.yaml ~/.config/nextcloud-uploader/config.yaml

In ~/.config/nextcloud-uploader/config.yaml muss mindestens der lokale Quellordner angepasst werden. Das Kennwort wird nicht in YAML gespeichert:

export NEXTCLOUD_APP_PASSWORD='mein-app-passwort'
nextcloud-uploader --dry-run
nextcloud-uploader

Der Quellordner kann pro Lauf angegeben werden und überschreibt dann upload.source:

nextcloud-uploader --source /pfad/zu/meinen/medien --dry-run
nextcloud-uploader --source /pfad/zu/meinen/medien

--dry-run darf Nextcloud lesen und für einen sicheren Duplikatvergleich Dateien streamen, ändert aber weder lokale noch entfernte Dateien.

Verhalten bei Kollisionen

Existiert der ursprüngliche Dateiname, prüft das Programm nacheinander _1, _2 usw. Kandidaten gleicher Größe werden per SHA-256 vollständig verglichen. Bei identischem Inhalt wird nur die lokale Kopie gelöscht. Bei unterschiedlichem Inhalt wird der nächste Name geprüft. Ein neuer Upload erfolgt zunächst unter einem temporären Namen und wird anschließend ohne Überschreibrecht auf den endgültigen Namen verschoben.

Vorübergehende Serverantworten (404, 408, 429 und 5xx) werden mit den in nextcloud.retry_delays_seconds konfigurierten Pausen wiederholt. Nach einem unklaren PUT oder MOVE prüft der Uploader zunächst, ob die Datei trotz der Fehlerantwort angekommen ist. Authentifizierungsfehler und echte Namenskollisionen werden nicht blind wiederholt.

Cron

Beispiel für einen Lauf alle zehn Minuten, wobei das Passwort aus einer nur für den Benutzer lesbaren Environment-Datei geladen wird:

*/10 * * * * . "$HOME/.config/nextcloud-uploader.env" && /pfad/.venv/bin/nextcloud-uploader >> "$HOME/nextcloud-uploader.log" 2>&1

Beispielinhalt der Environment-Datei:

NEXTCLOUD_APP_PASSWORD='mein-app-passwort'
export NEXTCLOUD_APP_PASSWORD

Die Datei sollte mit chmod 600 geschützt werden. Ein Prozess-Lock verhindert überlappende Läufe für denselben Quellordner.

Exitcodes

  • 0: Alle verarbeitbaren Dateien wurden erfolgreich behandelt.
  • 1: Mindestens eine Datei ist fehlgeschlagen; sie bleibt lokal erhalten.
  • 2: Konfiguration, ExifTool oder Prozess-Lock ist fehlerhaft.

Dateien, deren letzte Änderung weniger als fünf Minuten zurückliegt, werden auf einen späteren Lauf verschoben. Nicht unterstützte Dateien, Symlinks und leere Unterordner bleiben unverändert.

Entwicklung

pip install -e '.[test]'
pytest