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.

Check installed version:

photo-tools --version

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.1.tar.gz (14.6 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.1-py3-none-any.whl (15.9 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: photo_tools_cli-0.3.1.tar.gz
  • Upload date:
  • Size: 14.6 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.1.tar.gz
Algorithm Hash digest
SHA256 d143156aba04a1543d9a90beba61138516e2e7eac900e7785ed0621c7eafede1
MD5 7eb0c497483d4fcd68749d4dd7852ef3
BLAKE2b-256 1d18ceb82dbc14f82e6f12a13b51900326c05bbf68c912257d17d227a42f9ef5

See more details on using hashes here.

Provenance

The following attestation bundles were made for photo_tools_cli-0.3.1.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.1-py3-none-any.whl.

File metadata

  • Download URL: photo_tools_cli-0.3.1-py3-none-any.whl
  • Upload date:
  • Size: 15.9 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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 ea636e0120ef892a1f96e88cd00beba6ced414bd6f3523a86776a791ed835742
MD5 e35c9713daaf0b41b035d8d80c48d8b9
BLAKE2b-256 62811952fd712ee4cf80c129d29caf433e3fbd479afa51c961c947a8d4e61ffb

See more details on using hashes here.

Provenance

The following attestation bundles were made for photo_tools_cli-0.3.1-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