From 31af44dd2a8165e0f025c09fca1cbf640cfe0404 Mon Sep 17 00:00:00 2001 From: Bence Ferdinandy Date: Mon, 2 Jun 2025 03:58:58 +0200 Subject: [PATCH] feat: add --json-output option to upload command (#18845) * fix(docs): update the cli upload usage The cli upload usage is missing some options compared to what is the current output of `immich upload --help`. Update the docs accordingly. Signed-off-by: Bence Ferdinandy * feat(cli): add --json-output option to upload command Add an option that allows retrieving per-file information about the upload process. The output includes the newFiles, duplicates and newAssets lists, but could accommodate more information later if needed. One use case this allows for is using --dry-run to get a list of all the files that would be uploaded, and checking them manually before an upload. This can be particularly useful when a curated subset of images have already been uploaded to immich and we want to double check for some stragglers without uploading everything to immich. The upload command has a few lines of logging, so to get an actually parsable json one needs to strip those lines: immich upload --dry-run * | tail -n +4 | jq .newFiles[] Signed-off-by: Bence Ferdinandy --------- Signed-off-by: Bence Ferdinandy --- cli/src/commands/asset.ts | 4 +++ cli/src/index.ts | 5 +++ docs/docs/features/command-line-interface.md | 35 ++++++++++++++------ 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/cli/src/commands/asset.ts b/cli/src/commands/asset.ts index d06b30e984..edb24e2f67 100644 --- a/cli/src/commands/asset.ts +++ b/cli/src/commands/asset.ts @@ -43,6 +43,7 @@ export interface UploadOptionsDto { concurrency: number; progress?: boolean; watch?: boolean; + jsonOutput?: boolean; } class UploadFile extends File { @@ -65,6 +66,9 @@ class UploadFile extends File { const uploadBatch = async (files: string[], options: UploadOptionsDto) => { const { newFiles, duplicates } = await checkForDuplicates(files, options); const newAssets = await uploadFiles(newFiles, options); + if (options.jsonOutput) { + console.log(JSON.stringify({ newFiles, duplicates, newAssets }, undefined, 4)); + } await updateAlbums([...newAssets, ...duplicates], options); await deleteFiles(newFiles, options); }; diff --git a/cli/src/index.ts b/cli/src/index.ts index 5da4b50722..a0392186c0 100644 --- a/cli/src/index.ts +++ b/cli/src/index.ts @@ -68,6 +68,11 @@ program .env('IMMICH_UPLOAD_CONCURRENCY') .default(4), ) + .addOption( + new Option('-j, --json-output', 'Output detailed information in json format') + .env('IMMICH_JSON_OUTPUT') + .default(false), + ) .addOption(new Option('--delete', 'Delete local assets after upload').env('IMMICH_DELETE_ASSETS')) .addOption(new Option('--no-progress', 'Hide progress bars').env('IMMICH_PROGRESS_BAR').default(true)) .addOption( diff --git a/docs/docs/features/command-line-interface.md b/docs/docs/features/command-line-interface.md index 1ab79ee3f1..436b499e50 100644 --- a/docs/docs/features/command-line-interface.md +++ b/docs/docs/features/command-line-interface.md @@ -90,19 +90,22 @@ Usage: immich upload [paths...] [options] Upload assets Arguments: -paths One or more paths to assets to be uploaded + paths One or more paths to assets to be uploaded Options: --r, --recursive Recursive (default: false, env: IMMICH_RECURSIVE) --i, --ignore [paths...] Paths to ignore (default: [], env: IMMICH_IGNORE_PATHS) --h, --skip-hash Don't hash files before upload (default: false, env: IMMICH_SKIP_HASH) --H, --include-hidden Include hidden folders (default: false, env: IMMICH_INCLUDE_HIDDEN) --a, --album Automatically create albums based on folder name (default: false, env: IMMICH_AUTO_CREATE_ALBUM) --A, --album-name Add all assets to specified album (env: IMMICH_ALBUM_NAME) --n, --dry-run Don't perform any actions, just show what will be done (default: false, env: IMMICH_DRY_RUN) --c, --concurrency Number of assets to upload at the same time (default: 4, env: IMMICH_UPLOAD_CONCURRENCY) ---delete Delete local assets after upload (env: IMMICH_DELETE_ASSETS) ---help display help for command + -r, --recursive Recursive (default: false, env: IMMICH_RECURSIVE) + -i, --ignore Pattern to ignore (env: IMMICH_IGNORE_PATHS) + -h, --skip-hash Don't hash files before upload (default: false, env: IMMICH_SKIP_HASH) + -H, --include-hidden Include hidden folders (default: false, env: IMMICH_INCLUDE_HIDDEN) + -a, --album Automatically create albums based on folder name (default: false, env: IMMICH_AUTO_CREATE_ALBUM) + -A, --album-name Add all assets to specified album (env: IMMICH_ALBUM_NAME) + -n, --dry-run Don't perform any actions, just show what will be done (default: false, env: IMMICH_DRY_RUN) + -c, --concurrency Number of assets to upload at the same time (default: 4, env: IMMICH_UPLOAD_CONCURRENCY) + -j, --json-output Output detailed information in json format (default: false, env: IMMICH_JSON_OUTPUT) + --delete Delete local assets after upload (env: IMMICH_DELETE_ASSETS) + --no-progress Hide progress bars (env: IMMICH_PROGRESS_BAR) + --watch Watch for changes and upload automatically (default: false, env: IMMICH_WATCH_CHANGES) + --help display help for command ``` @@ -172,6 +175,16 @@ By default, hidden files are skipped. If you want to include hidden files, use t immich upload --include-hidden --recursive directory/ ``` +You can use the `--json-output` option to get a json printed which includes +three keys: `newFiles`, `duplicates` and `newAssets`. Due to some logging +output you will need to strip the first three lines of output to get the json. +For example to get a list of files that would be uploaded for further +processing: + +```bash +immich upload --dry-run . | tail -n +4 | jq .newFiles[] +``` + ### Obtain the API Key The API key can be obtained in the user setting panel on the web interface.