Skip to main content

Python CLI tools for photography workflows

Project description

CI

Photo Tools CLI

Command-line tools for organising photos by date, managing RAW/JPG pairs, and optimising images.

Changelog

See CHANGELOG.md for release history.

Supported formats

  • RAW: .cr2, .cr3, .nef, .arw, .raf, .orf, .rw2, .dng, .pef, .srw, .x3f
  • JPG: .jpg, .jpeg

⚠️ Note: Detection is based on file extensions only (case-insensitive). Files with incorrect or missing extensions may not be handled correctly.

Prerequisites - System Tools

This project depends on external system tools in addition to Python.

ExifTool

Used for extracting image metadata (including RAW formats).

  • Supports all major image formats, including RAW
  • Provides consistent metadata fields across formats
  • More reliable than Python-only EXIF libraries

If exiftool is not installed, the CLI will fail with a clear error message and exit code 1.

Install (macOS)

brew install exiftool

On Linux, install via your package manager (e.g. apt install exiftool).

Installation

Using pipx (recommended)

pipx install photo-tools-cli

Installs the CLI in an isolated environment and makes photo-tools available globally, avoiding dependency conflicts.

Using pip (if pipx not available)

pip install photo-tools-cli

Local development

Clone the repository and install:

pip install -e .
pip install --group dev -e .

Usage

List available commands:

photo-tools --help

Each command provides detailed usage, including arguments and options:

photo-tools <command> --help

Note: All commands currently process files in the top-level input directory only.

Global flags

All commands support:

  • --dry-run — preview changes without modifying files
  • --verbose / -v — show per-file output

Flags can be combined:

photo-tools <command> ... --dry-run --verbose

Organise by date (by-date)

  • Organise images into date-based folders (YYYY-MM-DD, optional suffix)
  • Files are moved (not copied) into the output directory
  • If a destination file already exists, it is skipped (no overwrite)
photo-tools by-date <INPUT_DIR> <OUTPUT_DIR>
photo-tools by-date <INPUT_DIR> <OUTPUT_DIR> --suffix <SUFFIX>

Separate RAW files (raws)

  • Move RAW images into a raws/ subfolder within the input directory
  • Non-RAW files are left unchanged
  • Files are moved (not copied) in place
  • If a destination file already exists, it is skipped (no overwrite)
photo-tools raws <INPUT_DIR>

Clean unpaired RAW files (clean-raws)

  • Move RAW files to raws-to-delete/ if no matching JPG (same prefix) exists
  • Matching is based on filename prefix (e.g. abcd.RAF matches abcd_edit.jpg)
  • Files are moved (not deleted), making the operation reversible
photo-tools clean-raws <RAW_DIR> <JPG_DIR>

Keep RAW files for 5-star JPGs (keep-5star-raws)

  • Move RAW files to raws-5-star/ if a matching JPG has a 5-star rating
  • Ratings are read from the JPG files, not the RAW files
  • Matching is based on filename prefix (e.g. abcd.RAF matches abcd.jpg or abcd_edit.jpg)
  • Files are moved (not copied), making the operation reversible
photo-tools keep-5star-raws <RAW_DIR> <JPG_DIR>

Optimise images (optimise)

  • Resize images to a maximum width of 2500px
  • Choose the highest quality that results in a file size ≤ 500 KB (never below 70%)
  • Saves optimised images with prefix lq_ in the same directory (overwrites existing files)
photo-tools optimise <INPUT_DIR>

Local Development Setup

Data

For convenience during development, you can create a local structure:

mkdir -p data/input data/output

Place test photos in:

data/input/

Running the CLI

You can run the CLI module directly for testing:

python -m photo_tools.cli by-date ./data/input ./data/output

Running tests

This project uses pytest:

pytest

Makefile

Common development tasks are available via the Makefile.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

photo_tools_cli-0.3.0.tar.gz (14.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

photo_tools_cli-0.3.0-py3-none-any.whl (15.4 kB view details)

Uploaded Python 3

File details

Details for the file photo_tools_cli-0.3.0.tar.gz.

File metadata

  • Download URL: photo_tools_cli-0.3.0.tar.gz
  • Upload date:
  • Size: 14.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for photo_tools_cli-0.3.0.tar.gz
Algorithm Hash digest
SHA256 17f73282ea187495a41918083b35e8a8ca79be77877e967a4ab0bd6c86c076e5
MD5 df63afa1e8972c1b40d9aa6bb04b7fc9
BLAKE2b-256 dc5a4a7c66eb433660e5624c48f5a70a6b7053e6d5e2877aeb6a1f5b246d332b

See more details on using hashes here.

Provenance

The following attestation bundles were made for photo_tools_cli-0.3.0.tar.gz:

Publisher: publish.yml on aga87/python-photo-tools

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file photo_tools_cli-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: photo_tools_cli-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 15.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for photo_tools_cli-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a2cf5b326f693d99a719c8c0b9aa910ecb74438cd9ab8e533eff8c36a938e1f9
MD5 174452d80c626e79675b84e985a11e41
BLAKE2b-256 a60371ea1f032939ca1366a7a964f279328d4696b0586204384e87367bc8d0e6

See more details on using hashes here.

Provenance

The following attestation bundles were made for photo_tools_cli-0.3.0-py3-none-any.whl:

Publisher: publish.yml on aga87/python-photo-tools

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page