Update: 2026-10-28 – Skript-Version 1.1.0. Wer das ursprüngliche Skript verwendet, sollte es ersetzen. Was sich geändert hat und warum:
- Geänderte Dateien werden nachkopiert. Version 1.0.0 hat nur geprüft, ob eine Datei schon im Backup liegt. Wurde ein JPG danach nochmals exportiert oder z.B. mit meinem Metadaten-Skript bearbeitet, blieb auf Amazon die alte Version liegen. Jetzt werden Größe und Änderungszeit verglichen.
- Schutz vor kaputten Dateien. Eine geänderte Datei ersetzt das Backup nur, wenn sie noch ein gültiges JPG ist. Von Ransomware verschlüsselte Dateien überschreiben also nicht die gesicherten Originale.
.JPGin Großbuchstaben und.jpegwerden jetzt mitgenommen, bisher fielen z.B. JPGs direkt aus der Kamera durch.- Parameter statt fixer Pfade, mehrere Jahre in einem Aufruf und
-WhatIffür einen Probelauf, der nur anzeigt, was kopiert würde. - Aufgeräumt. Die undefinierte
$exclusionListist weg, die Funktionsnamen folgen der PowerShell-Konvention Verb-Nomen. - Neu im Text: ein fertiges launchd-Beispiel für den automatischen Lauf und die Antwort auf die HEIC-Frage vom Ende.
Ich mache Fotos - ziemlich viele Fotos. Nicht nur im Rahmen meiner fotografischen beruflichen Tätigkeit, sondern auch mit dem Handy. Mein Archiv ist aktuell 13TB - und die drei mal gespeichert. Und nachdem mein Archiv (neben den Negativen, die ich übrigens auch gescannt digital habe) mein wichtigstes Asset ist, darf mir dieses nicht verloren gehen.
Wer nach einer einfachen Methode sucht, seine Fotos aus dem Apple Universum rauszubekommen (ohne mühsame Umwege und die auch mit 50.000 Fotos+ funktioniert), dem sei mein Blogpost hierzu angeraten.
Klassisch: Die 3-2-1 Backup Regel
In meiner bisherigen Struktur für Backups befolge ich die 3-2-1 Regel und bin damit bisher recht gut gefahren. Drei Kopien auf zwei unterschiedlichen Devices/Speichermedien und eine Kopie offsite bzw. in der Cloud. Platten- und sogar NAS-Ausfälle konnte ich damit über die Jahre gut überstehen. Trotzdem habe ich mir aus unterschiedlichen Gründen eine weitere Schiene überlegt…
Update: 2026-09-22 – Das „eine Kopie in der Cloud” ist keine Garantie. Im Krieg zwischen den USA und Israel auf der einen und dem Iran auf der anderen Seite, der Ende Februar 2026 begann, hat der Iran mehrfach die AWS-Rechenzentren in Bahrain mit Drohnen und Raketen angegriffen. Im September 2026 hat AWS die Wiederherstellung nach Monaten aufgegeben: Alle drei Verfügbarkeitszonen der Region Bahrain sind verloren, Daten, die ausschließlich dort lagen, sind endgültig weg. Und das, obwohl es genau diese drei Availability Zones gab, die eigentlich für so einen Fall da sein sollten - mehrere voneinander getrennte Rechenzentren, damit der Ausfall eines einzelnen nichts kostet. Sie schützen also maximal vor technischen Gebrechen, Feuer, Stromausfall und dergleichen, aber nicht vor gezielter Zerstörung durch Krieg, die alle drei gleichzeitig trifft. Die Kunden wurden auf ihre eigenen Sicherungen verwiesen (heise-Artikel, Video von heise & c’t). Ein Cloud-Anbieter ist also genau eine der drei Kopien und nicht mehr - wer nur dort speichert, hat kein Backup, sondern eine einzige Kopie an einem fremden Ort. Die „1” in 3-2-1 schützt vor Wohnungsbrand und Einbruch, die anderen beiden Kopien zu Hause schützen vor der Cloud.
Die nächste Stufe: Die 4-3-2 Regel
Vier Kopien auf drei unterschiedlichen Speichermedien und zwei davon offline. Das klingt nach viel Aufwand, ist es aber insofern nicht weil man
- das Kopieren automatisieren kann (mehr dazu unten) und
- man nicht notwendigerweise das komplette Set von Daten für die vierte Kopie speichern muss
Welche Daten sind nun in der +1 Variante gesichert? Ich habe mich dazu entschieden aus meinem Fotoarchiv nur die Daten zusätzlich zu sichern, die ich Kunden abgeliefert habe. Das sind zum einen wesentlich weniger Dateien als ich angefertigt habe und diese sind auch wesentlich kleiner, da das immer JPGs sind.
Für mein komplettes Archiv arbeite ich weiterhin mit 3-2-1.
Der Blogposttitel hat es schon verraten: die abgelieferten JPGs sollen zusätzlich auf Amazon Photos gesichert werden. Das bringt folgende Vorteile:
- Ein weiterer Speicherort
Für alle Fälle… - Schutz gegen Ransomware
Im Gegensatz zu meinem 3-2-1 Datenfluss, bei dem jede geänderte Datei sofort auf die Kopien weitergeschoben wird, läuft dieses Backup zeitversetzt. Dazu ersetzt das Skript ein gesichertes JPG nur durch ein gültiges JPG. Sollte ich Opfer von Ransomware oder ähnlicher Software werden, liegen auf Amazon Photos mit guter Wahrscheinlichkeit noch meine originalen JPGs. - Online-Verfügbarkeit
JPGs in Amazon Photos können von überall angesehen bzw. auch downgeloaded werden. Man hat damit also auf alle Fotos, die bearbeitet bzw. abgeliefert wurden Zugriff. - Unlimitierter Speicher
Mit Prime-Mitgliedschaft, zumindest für Fotos (Videos nur 5 GB), eine Einschränkung, mit der wir in diesem Zusammenhang gut leben können. Hier noch eine genaue Liste, welche Dateitypen akzeptiert werden.
Organisation - Datei- und Verzeichnisstruktur
Wichtig: Die folgenden Gedanken funktionieren nur gut, wenn man sich an eine Namenskonvention gehalten hat.
Als Fotograf arbeite ich viel im Eventbereich bzw. für Firmen. Daher habe ich mich vor Jahren dazu entschieden für jeden Job/jedes Shooting einen eigenen Lightroom-Katalog zu machen. Die Kataloge liegen in einem Verzeichnis pro Jahr. Dies sieht bei mir dann zum Beispiel so aus:

Innerhalb eines solchen Folders findet sich dann folgendes:
- Der Lightroom Katalog für das Shooting
- Ein Verzeichnis Originals mit allen RAW und Video Dateien
- Ein oder mehrere Verzeichnisse mit _Export im Namen - also beispielsweise zusätzlich eine kleine, stärker komprimierte Version für das Web mit _ExportWeb etc
- Optional ein Verzeichnis Organisation mit wichtigen weiteren Infos wie Abläufe, Akkreditierungen etc. (das wird von Amazon Photos aber nicht beachtet)
Diese Standardisierung der Verzeichnisnamen ist nun vorteilhaft bei der Auswahl der zu speichernden Fotos.

Folgendes soll also auf Amazon Photos gespeichert werden:
- Alle JPG Dateien
- In den Verzeichnissen der einzelnen Jahre (2023, 2022 etc)
- In Unterverzeichnissen die _Export im Namen haben
- in genau der gleichen Struktur wie in der Quelle
Amazon Photos kann zwar automatisch ganze Verzeichnisse hochladen, aber nicht so spezifisch, wie ich meine Anforderungen hier habe. Insofern nehme ich einen Umweg und bereite auf meiner lokalen Festplatte ein eigenes Verzeichnis für Amazon vor, in dem alle Fotos hochgeladen werden sollen. Den Nachteil der doppelten JPG Dateien nur für Amazon nehme ich gerne in Kauf, da die JPG Dateien relativ klein sind und auch nur die beinhalten, die ich tatsächlich abgeliefert habe.
Say Hi! to PowerShell on macOS
Aus meiner Softwareentwicklerzeit unter Windows kommen nun meine PowerShell Kenntnisse zugute. Das folgende PowerShell-Skript grast die entsprechenden Verzeichnisse ab und kopiert (falls nötig) die JPGs in die Amazon Photos Verzeichnisstruktur. Es braucht PowerShell 7 (pwsh), das es für macOS, Linux und Windows gibt.
# Backup-AmazonPhotos
<#
.SYNOPSIS
Copies all delivered JPGs from the *Export* folders of a photo
archive into a separate folder that Amazon Photos backs up.
.DESCRIPTION
This script
1. Walks recursively through one or more year folders
2. Picks all *.jpg/*.jpeg files inside folders with "Export" in the name
3. Copies them to the backup folder in the same structure
4. Copies a file again if size or modification time has changed
This software is provided 'as is', without any warranties
or representations of any kind, whether express or implied,
including but not limited to warranties of merchantability,
fitness for a particular purpose, or non-infringement.
.CHANGELOG
1.1.0 - 2026-10-28 - ms - Include .JPG/.jpeg, copy changed files again
unless they are no valid JPG anymore,
parameters instead of hard-coded paths,
-WhatIf support, verb-noun function names.
1.0.0 - 2023-08-31 - ms - Initial release.
.PARAMETER SourceDirectories
Year folders below RootPhotoDir, e.g. "Pictures2023", "Pictures2022".
.PARAMETER RootPhotoDir
Main directory for photos, contains the year folders.
.PARAMETER BackupDir
Folder that Amazon Photos uploads from.
#>
#Requires -Version 7
[CmdletBinding(SupportsShouldProcess)]
param(
[Parameter(Mandatory = $true, Position = 0)]
[string[]] $SourceDirectories,
[string] $RootPhotoDir = "/Volumes/iMac External Disc 3/",
[string] $BackupDir = "/Volumes/iMac External Disc 3/AmazonPhotosBackup/"
)
function Copy-ChangedFile {
[CmdletBinding(SupportsShouldProcess)]
param(
[Parameter(Mandatory = $true)]
[System.IO.FileInfo] $File,
[Parameter(Mandatory = $true)]
[string] $DestinationFolderPath
)
$destination = Join-Path $DestinationFolderPath $File.Name
$existing = Get-Item -LiteralPath $destination -ErrorAction SilentlyContinue
# Skip files that are already there with the same size and date
if ($existing -and
$existing.Length -eq $File.Length -and
$existing.LastWriteTimeUtc -eq $File.LastWriteTimeUtc) {
return $false
}
# Never overwrite a backup with something that is no JPG anymore
# (e.g. a file encrypted by ransomware): JPGs start with FF D8 FF
$header = [byte[]]::new(3)
$stream = [System.IO.File]::OpenRead($File.FullName)
try { $read = $stream.Read($header, 0, 3) } finally { $stream.Dispose() }
if ($read -lt 3 -or $header[0] -ne 0xFF -or $header[1] -ne 0xD8 -or $header[2] -ne 0xFF) {
Write-Warning "$($File.FullName) is no valid JPG - skipped"
return $false
}
if ($PSCmdlet.ShouldProcess($File.FullName, "Copy to $DestinationFolderPath")) {
# Make sure the destination folder exists
if (-not (Test-Path -LiteralPath $DestinationFolderPath)) {
New-Item -ItemType Directory -Path $DestinationFolderPath | Out-Null
}
# Copy-Item keeps the modification time, so the next run can compare it
Copy-Item -LiteralPath $File.FullName -Destination $destination -Force
$action = if ($existing) { "updated" } else { "copied" }
Write-Host "$($File.FullName) $action" -ForegroundColor Green
}
return $true
}
function Backup-PhotoDirectory {
[CmdletBinding(SupportsShouldProcess)]
param(
# The source directory, e.g. Pictures2023
[Parameter(Mandatory = $true)]
[string] $SourceDirectory
)
$sourceRoot = Join-Path $RootPhotoDir $SourceDirectory
$backupRoot = Join-Path $BackupDir $SourceDirectory
if (-not (Test-Path -LiteralPath $sourceRoot)) {
Write-Warning "$sourceRoot not found - is the disc mounted?"
return
}
# Only JPGs (any case) below a folder with "Export" in its name;
# Lightroom catalogs, previews and .DS_Store are no JPGs and drop out here
$files = Get-ChildItem -LiteralPath $sourceRoot -Recurse -File |
Where-Object { $_.Extension -in ".jpg", ".jpeg" -and $_.DirectoryName -like "*Export*" }
$count = 0
foreach ($file in $files) {
# Same relative path below the backup folder
$relative = [System.IO.Path]::GetRelativePath($sourceRoot, $file.DirectoryName)
$target = Join-Path $backupRoot $relative
if (Copy-ChangedFile -File $file -DestinationFolderPath $target) { $count++ }
}
Write-Host "${SourceDirectory}: $count file(s) new or changed" -ForegroundColor Cyan
}
foreach ($dir in $SourceDirectories) {
Backup-PhotoDirectory -SourceDirectory $dir
}Sieht nach viel Code aus (tut es bei PowerShell immer), ist aber im Grunde einfach: die angegebenen Jahresverzeichnisse werden rekursiv durchlaufen, und alle JPGs, die in einem Export-Verzeichnis liegen, landen in der gleichen Struktur im Verzeichnis, das Amazon Photos regelmäßig sichert. Neue Dateien werden kopiert, geänderte ersetzt, alles andere bleibt, wie es ist.
Aufgerufen wird es so:
# Probelauf: zeigt nur an, was kopiert würde
./Backup-AmazonPhotos.ps1 Pictures2023, Pictures2022 -WhatIf
# echter Lauf
./Backup-AmazonPhotos.ps1 Pictures2023, Pictures2022Bei mir sind in dem Verzeichnis aktuell 140GB und der initiale Upload dauerte ca. 13 Stunden.
Das Script selbst wird am besten mit Visual Studio Code bearbeitet/getestet:

Play it again, Sam! - Das Backup regelmäßig updaten
In meiner Backupstruktur ist nichts manuell - sonst würde ich das bei der ersten möglichen Gelegenheit vergessen… Daher muss dieses Skript nun noch regelmäßig ausgeführt werden. Da nur neue und geänderte JPGs kopiert werden, ist ein wöchentlicher oder sogar täglicher Lauf kein Aufwand. Auf macOS ist dafür launchd zuständig. Diese Datei als ~/Library/LaunchAgents/net.seirer.backup-amazonphotos.plist speichern, Pfade anpassen, fertig:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>net.seirer.backup-amazonphotos</string>
<key>ProgramArguments</key>
<array>
<string>/opt/homebrew/bin/pwsh</string>
<string>-NoProfile</string>
<string>-Command</string>
<string>& ~/Scripts/Backup-AmazonPhotos.ps1 Pictures2026, Pictures2025</string>
</array>
<!-- jeden Sonntag um 3:00 -->
<key>StartCalendarInterval</key>
<dict>
<key>Weekday</key>
<integer>0</integer>
<key>Hour</key>
<integer>3</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
<key>StandardOutPath</key>
<string>/tmp/backup-amazonphotos.log</string>
<key>StandardErrorPath</key>
<string>/tmp/backup-amazonphotos.log</string>
</dict>
</plist>Aktiviert wird der Job mit:
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/net.seirer.backup-amazonphotos.plistSchläft der Mac um 3:00, holt launchd den Lauf beim Aufwachen nach. Liegen die Fotos auf einer externen Platte, braucht pwsh unter Systemeinstellungen, Datenschutz & Sicherheit, „Festplattenvollzugriff”, sonst bleibt das Log leer und das Backup auch. Unter Windows erledigt die Aufgabenplanung dasselbe.
Einschränkungen und weitere Überlegungen
Warum nicht Dropbox, Google Drive etc?
Ähnlich zu Amazon Photos kann man seine JPGs auch auf Dropbox, Google Drive oder ähnliches legen. Hier sind aber, abhängig von den Datenmengen, bald zusätzliche Kosten damit verbunden - Amazon Photos ist mit Prime für JPGs und RAWs aktuell unlimitiert. Dafür könnte man auf Dropbox oder Google Drive zusätzliche, wichtige Dateien wie PDFs mitsichern.
Warum PowerShell und nicht ein Shellscript oder Python?
Das ginge natürlich ebenso - einfach das nehmen, mit dem man am schnellsten zum Ziel kommt ;)
Warum nicht mit dafür gedachter Software wie CCC (Carbon Copy Cloner) arbeiten?
Die Requirements waren so speziell, dass eine Script-basierte Lösung die flexibelste erschien. Und sie kostet keine Lizenzkosten (wiewohl ich CCC für meine sonstigen 3-2-1 Backups verwende)
Was ist mit Fotos vom Handy?
Gute Frage, die könnten ebenfalls zusätzlich auf Amazon Photos gespeichert werden. Da ich auf dem iPhone allerdings HEIC als Format eingestellt habe, müsste ich die zuerst konvertieren. Das erledigt osxphotos aus meinem iPhone-Backup-Post gleich beim Export: mit der Option --convert-to-jpeg landen die Handyfotos als JPG im Exportordner und können von dort mitgesichert werden.
Fragen zu Backup-Themen? Unter macOS oder Windows? Unklarheiten bei Lightroom oder der Bildverwaltung?
Gerne einfach melden, ich beschäftige mich mit dem Thema seit 2011 und meine Skills als Softwareentwickler und Techniker sind in dem Bereich oftmals hilfreich ;)
