Documentation

Everything you need to know about using phopy for your photo organization workflow.

Quick Start

Get up and running with phopy in under a minute.

Basic Usage

Copy all photos from a source directory to a target directory:

phopy --source /path/to/source --target /path/to/target

Or use the short flags:

phopy -s /path/to/source -t /path/to/target
๐Ÿ’ก Tip

Use --dry-run to preview what would be copied without actually copying any files.

Installation

Homebrew (macOS/Linux)

The recommended way to install phopy:

brew install svenliebig/tap/phopy

Manual Installation

Download the latest release from the GitHub Releases page and move the binary to a directory in your PATH.

# Example for macOS/Linux
mv phopy /usr/local/bin/
chmod +x /usr/local/bin/phopy

Verify Installation

phopy --help

CLI Options

Complete reference for all command-line options.

Option Short Description Default
--source -s The source directory to copy photos from. This is where your camera or SD card photos are located. Required
--target -t The target directory to copy photos to. This is your photo archive or destination folder. Required
--dry-run -d Perform a dry run without actually copying any files. Shows what would be copied. false
--verbose -v Enable verbose output with detailed logging about the scanning and copying process. false
--override -o Allow overwriting files that already exist in the target directory. Without this flag, existing files are skipped. false
--from -f Start date filter in YYYY-MM-DD format. Only copy photos taken on or after this date. None
--until -u End date filter in YYYY-MM-DD format. Only copy photos taken on or before this date (inclusive, until 23:59:59). None
โ„น๏ธ Note

The --source and --target options are required unless set via environment variables.

Environment Variables

Configure phopy using environment variables for convenient repeated use.

Variable Description Equivalent Flag
PHOPY_SOURCE_DIR Default source directory for photo imports --source, -s
PHOPY_TARGET_DIR Default target directory for photo exports --target, -t
PHOPY_VERBOSE Enable verbose output (values: true, 1, yes, y) --verbose, -v
PHOPY_FROM Default start date filter (YYYY-MM-DD) --from, -f
PHOPY_START_DATE Alias for PHOPY_FROM --from, -f
PHOPY_UNTIL Default end date filter (YYYY-MM-DD) --until, -u
PHOPY_END_DATE Alias for PHOPY_UNTIL --until, -u

Example: Setting Environment Variables

# Add to your ~/.bashrc or ~/.zshrc
export PHOPY_TARGET_DIR="$HOME/Photos/Archive"
export PHOPY_VERBOSE=true

# Now you can run with just the source:
phopy -s /Volumes/SD_CARD/DCIM
๐Ÿ’ก Tip

CLI flags always take precedence over environment variables when both are specified.

Supported Formats

phopy recognizes the following image file formats:

RAW Formats

These formats are prioritized during copying:

.arw .cr2 .cr3 .nef .raf .rw2 .orf .dng
Extension Manufacturer
.arwSony
.cr2Canon (older)
.cr3Canon (newer)
.nefNikon
.rafFujifilm
.rw2Panasonic
.orfOlympus
.dngAdobe Digital Negative (universal)

JPEG Formats

Standard JPEG files are copied only when no matching RAW exists:

.jpg .jpeg

How It Works

phopy follows an opinionated workflow designed for photographers who shoot RAW+JPEG:

  1. Scan: phopy walks through the source directory and identifies all RAW and JPEG files
  2. Filter: Files are filtered based on date range (if specified) using EXIF metadata
  3. Match: JPEGs are checked for matching RAW files (same base filename)
  4. Plan: A copy plan is generated showing what will be copied
  5. Execute: Files are copied with progress feedback

RAW/JPEG Handling

The core feature of phopy is intelligent RAW/JPEG handling:

Example Scenario

Given these files in your source directory:

IMG_001.ARW    # RAW file
IMG_001.JPG    # JPEG (will be skipped - RAW exists)
IMG_002.ARW    # RAW file
IMG_002.JPG    # JPEG (will be skipped - RAW exists)  
IMG_003.JPG    # JPEG (will be copied - no RAW)
HDR_001.JPG    # JPEG (will be copied - no RAW)

phopy will copy:

And skip IMG_001.JPG and IMG_002.JPG because their corresponding RAW files are being copied.

Duplicate Detection

phopy checks if files already exist in the target directory before copying:

โš ๏ธ Warning

When using --override, make sure you understand which files will be replaced. Use --dry-run first to preview the changes.

Date Filtering

Filter photos by their capture date using EXIF metadata:

# Copy photos from a specific date
phopy -s ./source -t ./target --from 2024-06-15 --until 2024-06-15

# Copy photos from a date range
phopy -s ./source -t ./target --from 2024-01-01 --until 2024-03-31

# Copy photos from a start date onwards
phopy -s ./source -t ./target --from 2024-06-01

# Copy photos up to an end date
phopy -s ./source -t ./target --until 2024-05-31

Date Format

Dates must be specified in YYYY-MM-DD format:

โ„น๏ธ EXIF Fallback

If a photo doesn't have EXIF date metadata, phopy falls back to the file's modification time. You'll see a warning in verbose mode when this happens.

Shell Completion

phopy supports shell completion for bash, zsh, fish, and PowerShell.

Bash

# Add to ~/.bashrc
source <(phopy completion bash)

Zsh

# Add to ~/.zshrc
source <(phopy completion zsh)

Fish

# Add to ~/.config/fish/config.fish
phopy completion fish | source

PowerShell

# Add to your PowerShell profile
phopy completion powershell | Out-String | Invoke-Expression

Examples

Common usage patterns for different photography workflows.

Import from SD Card

Copy all photos from your camera's SD card to your archive:

phopy --source /Volumes/SD_CARD/DCIM --target ~/Photos/Archive

Import Photos from a Trip

Copy only photos from a specific date range:

phopy -s /Volumes/SD_CARD/DCIM -t ~/Photos/Vacation2024 \
      --from 2024-07-01 --until 2024-07-14

Preview Before Copying

Use dry run mode to see what would be copied:

phopy -s ./source -t ./target --dry-run --verbose

Re-import with Override

Re-copy photos and replace existing files:

phopy -s /Volumes/SD_CARD/DCIM -t ~/Photos/Archive --override

Using Environment Variables

Set up defaults for repeated use:

# In your shell profile (~/.zshrc, ~/.bashrc)
export PHOPY_TARGET_DIR="$HOME/Photos/Archive"

# Now just specify the source
phopy -s /Volumes/SD_CARD/DCIM

# Or copy from today's shoot
phopy -s /Volumes/SD_CARD/DCIM --from 2024-06-15

Verbose Mode for Debugging

See detailed information about the scanning and copying process:

phopy -s ./source -t ./target --verbose

Need Help?

Found a bug or have a feature request? Open an issue on GitHub.

Open an Issue โ†’