A set of PowerShell scripts to download and organize iCloud media. The scripts use the awesome iCloud downloader from https://github.com/icloud-photos-downloader/icloud_photos_downloader to do the actual download. And the organization happens in a specific way, please read below.
Here is what the iCloudSync.ps1 script does in order:
-
Gets the settings from
iCloudSync.inifile. If the file does not exist, it creates it in the$env:AppData\iCloudSyncdirectory. -
If the
-installswitch is specified, it installs theiCloudSync.ps1script to run as a scheduled task. The settings for the scheduled task are in theiCloudSync.inifile. -
If the
-editSettingsswitch is specified, it opens theiCloudSync.inifile to be edited in the system default text editor. If you want to run the scripts as a scheduled task, do this first to view/modify the default settings. -
Syncs all media to the specified directory, based on settings in
iCloudSync.inifile. -
Processes all media downloaded in the media directory:
- Makes a backup of the touched media to the
backupDir(ifskipBackupis not set) - Renames the media with the pattern
yyyy.MM.dd.HH.mm.ss(controlled by theMediaFileNameFormatStringsetting iniCloudSync.ini) - Finds any duplicates and moves them to the
duplicatesDir(ifskipDuplicatesis not set) - Moves all media to the
destinationDir(ifskipOrganizeis not set) into the folder structureYear/Month/File.ext. IfvideosDestinationDiris specified, then moves all videos (filtered by VideoFilter iniCloudSync.ini) to that directory instead.
- Makes a backup of the touched media to the
There are two scripts you can use directly in PowerShell:
Sync with the default options:
./iCloudSync.ps1Sync by specifying the directories to sync to and the final destination:
./iCloudSync.ps1 -Directory 'Z:\@iCloud\.Organize' -DestinationDir = 'Z:\@iCloud'| Name | Type | Default | Description |
|---|---|---|---|
| directory | string | Z:\@iCloud\.Organize | The directory where the media will be downloaded |
| destinationDir | string | Z:\@iCloud | The directory where the media will be moved when organized |
| videosDestinationDir | string | Z:\@iCloud\Videos | The directory where the videos will be moved when organized |
| backupDir | string | Z:\@iCloud\.Organize\.Original | The directory where backups will be moved |
| duplicatesDir | string | Z:\@iCloud\.Organize\.Duplicates | The directory where the duplicate media will be moved |
| skipDownload | switch | false | Should the download step be skipped |
| skipProcessing | switch | false | Should the download step be skipped |
| skipBackup | switch | false | Should the backup step be skipped |
| skipRename | switch | false | Should the rename step be skipped |
| skipDuplicates | switch | false | Should the duplicates check step be skipped |
| skipOrganize | switch | false | Should the media organization step be skipped |
| install | switch | false | Installs the script as a scheduled task |
| editSettings | switch | false | Opens the iCloudSync.ini file to be edited |
Organize only:
./Organize-Media.ps1| Name | Type | Default | Description |
|---|---|---|---|
| directory | string | Z:\@iCloud\.Organize | The directory where the media will be downloaded |
| destinationDir | string | Z:\@iCloud | The directory where the media will be moved when organized |
| videosDestinationDir | string | Z:\@iCloud\Videos | The directory where the videos will be moved when organized |
| backupDir | string | Z:\@iCloud\.Organize\.Original | The directory where backups will be moved |
| duplicatesDir | string | Z:\@iCloud\.Organize\.Duplicates | The directory where the duplicate media will be moved |
| skipProcessing | switch | false | Should the download step be skipped |
| skipBackup | switch | false | Should the backup step be skipped |
| skipRename | switch | false | Should the rename step be skipped |
| skipDuplicates | switch | false | Should the duplicates check step be skipped |
| skipOrganize | switch | false | Should the media organization step be skipped |
These are the settings in the iCloudSync.ini that you can modify.
| Name | Value | Description |
|---|---|---|
| SettingsPath | $(Join-Path $env:AppData 'iCloudSync\iCloudSync.ini') | The path to the user settings file, you shouldn't have to change this |
| ImageFilter | \.(jpg|jpeg|png) | The extensions to filter images by |
| VideoFilter | \.(mov|3gp|mp4) | The extensions to filter videos by |
| MediaFilter | \.(jpg|jpeg|png|mov|3gp|mp4) | The combined list of media extensions |
| MediaFileNameFormatString | yyyy.MM.dd.HH.mm.ss | The format of the file name when renaming files |
| ScheduledTaskName | iCloudSync | The name of the scheduled task created with -install |
| RunEveryXHours | 12 | The repeat interval in hours for the scheduled task |
| PowerShellExePath | C:\Program Files\PowerShell\7\pwsh.exe | The path to the PowerShell executable for the scheduled task |
| PowerShellArguments | -ExecutionPolicy Bypass "$(Join-Path (Split-Path $PSScriptRoot -Parent) iCloudSync.ps1)" | The PowerShell arguments for the scheduled task |
| DownloaderExePath | $(Join-Path $PSScriptRoot 'tools\icloudpd-1.13.4-windows-amd64.exe') | The path to the icloudpd executable |
| DownloaderArguments | --skip-live-photos --folder-structure none --delete-after-download --no-progress-bar --recent 100 | The arguments used by the icloudpd downloader |
| JheadExePath | $(Join-Path $PSScriptRoot 'tools\jhead.exe') | The path to the jhead executable |
| ExifToolExePath | $(Join-Path $PSScriptRoot 'tools\exiftool.exe') | The path to the exiftool executable |
| CredentialsPath | $(Join-Path $env:AppData 'iCloudSync\Credentails.xml') | The path to where the credentials file is stored |
You can skip any of the steps the script takes by passing the appropriate skip parameter.
-
Passing
-skipDownloadskips the download step all together./iCloudSync.ps1 -skipDownload
-
Passing
-skipProcessingskips the processing steps all together./iCloudSync.ps1 -skipProcessing
-
Passing
-skipBackupskips the backup and it does not create a backup of the media./iCloudSync.ps1 -skipBackup
-
Passing
-skipRenameskips rename the downloaded media./iCloudSync.ps1 -skipRename
-
Passing
-skipDuplicatesskips the check for duplicates step./iCloudSync.ps1 -skipDuplicates
-
Passing
-skipOrganizeskips the organize step./iCloudSync.ps1 -skipOrganize
-
You can also pass all of them at once
./iCloudSync.ps1 -skipDownload -skipProcessing -skipBackup -skipRename -skipDuplicates -skipOrganize
There is a couple of parameters you can pass the script if you only want to simulate the work being done and not make any changes.
-
Passing
-whatIfwill output to the console all the actions the script will take, but not actually take them./iCloudSync.ps1 -whatIf
-
Passing
-debugwill output extra debug information./iCloudSync.ps1 -debug
-
You can also pass both
-whatIf -debugfor a combination of both./iCloudSync.ps1 -whatIf -debug