photosync

Crates.iophotosync
lib.rsphotosync
version0.1.1
created_at2026-01-12 18:03:04.316993+00
updated_at2026-01-14 16:09:35.190167+00
descriptionTool for copying photos from SD cards
homepage
repositoryhttps://github.com/rolandd/photosync
max_upload_size
id2038411
size140,764
Roland Dreier (rolandd)

documentation

README

Photosync

CI

A Rust utility for syncing photos from camera memory cards to organized directories based on EXIF metadata.

What It Does

Photosync scans source directories (typically mounted SD cards at /media/<username>) for photos and videos, extracts EXIF metadata, and copies files to a date-organized folder structure:

~/Pictures/<camera_dir>/YYYY/MM/DD/<original_filename>

For example, a photo shot on October 25, 2023 with a Canon EOS R6 would be copied to:

~/Pictures/CanonR6-images/2023/10/25/IMG_1234.CR3

The directory structure is configurable using a template system.

Multi-Platform Support (Experimental)

Note: Photosync is primarily developed and tested on Linux. Support for macOS and Windows is implemented but considered experimental and untested. Please verify your configuration with a dry run (-n) before usage.

macOS

  • Source: SD cards are typically mounted at /Volumes. Running photosync --init on macOS will automatically suggest source = "/Volumes" and exclude = ["Macintosh HD"] to avoid scanning your system drive.
  • Permissions: You may need to grant your terminal application permission to access "Removable Volumes" in System Settings.

Windows

  • Source: You generally need to specify a drive letter (e.g., source = "D:/").
  • Path Separators: Always use forward slashes (/) in configuration paths, even on Windows. For example, use D:/Photos or Canon/EOS/R6, not D:\Photos or Canon\EOS\R6.
  • Excludes: Creating a config with --init on Windows will default to excluding common system folders like System Volume Information and $RECYCLE.BIN.

Note on Exclusions

  • Case Sensitivity: The exclude list uses exact, case-sensitive matching. Ensure the casing in your config matches the actual directory names (e.g., "Macintosh HD", not "macintosh hd").

Installation

Requires Rust 2024 edition.

cargo install photosync
# Or build from source:
cargo build --release

Quick Start

# Create a configuration file
photosync --init

# Edit the config to add your camera mappings
# (location shown by --init output)

# Run a dry run to see what would be copied
photosync -n

# Sync your photos
photosync

Usage

# Run with defaults (scans /media/$USER, copies to ~/Pictures)
photosync

# Dry run to see what would be copied
photosync -n

# Override source and target directories
photosync --source /path/to/card --target /path/to/photos

# Use a custom directory structure
photosync --template "{year}/{month}/{camera}"

# Disable TUI for piping/scripting
photosync --no-tui

Command-Line Options

Option Description
--init Create a starter configuration file
-n, --dry-run Print what would be done without copying
--no-tui Disable interactive UI, use plain text output
--source <PATH> Override source directory
--target <PATH> Override target directory
--template <FMT> Override destination directory template

Configuration

Create photosync.toml in the current directory or ~/.config/photosync/photosync.toml:

# Optional: Override default paths
# Supported variables: $HOME, $XDG_PICTURES_DIR (also ${VAR} syntax)
[dirs]
source = "/media/roland"
target = "$XDG_PICTURES_DIR"
template = "{camera}/{year}/{month}/{day}"

# Map camera model substrings to destination folders
[cameras]
"EOS R6" = "CanonR6-images"
"6D" = "Canon6D-images"
"Hero13" = "GoPro-Hero13"
"HERO13" = "GoPro-Hero13"

Template System

The destination directory structure can be customized using the template option. The following tags are available:

  • {camera}: The matched camera directory name (from config)
  • {year}: 4-digit year (e.g., "2023")
  • {month}: 2-digit month (e.g., "10")
  • {day}: 2-digit day (e.g., "25")

The default template is {camera}/{year}/{month}/{day}.

Note on Safety:

  • All paths and templates must use forward slashes (/), not backslashes. They will be converted to the appropriate separator for your platform.
  • Camera directory names defined in the config must be relative paths and cannot contain .. (parent directory traversal).
  • The resulting path from the template is also validated to ensure it does not attempt to traverse outside the target directory.

Camera matching uses longest-match-first semantics, so more specific patterns take precedence.

Dependencies

  • nom-exif - EXIF parsing
  • clap - Command-line argument parsing
  • ratatui - Terminal UI
  • crossterm - Cross-platform terminal manipulation
  • walkdir - Recursive directory traversal
  • chrono - Date/time handling
  • dirs - Platform-specific standard directories (Pictures, config, etc.)
  • anyhow - Error handling
  • toml - Configuration file parsing

License

MIT License - Copyright 2026 Roland Dreier roland@kernel.org

Commit count: 28

cargo fmt