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
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 |
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
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:
| Extension | Manufacturer |
|---|---|
| .arw | Sony |
| .cr2 | Canon (older) |
| .cr3 | Canon (newer) |
| .nef | Nikon |
| .raf | Fujifilm |
| .rw2 | Panasonic |
| .orf | Olympus |
| .dng | Adobe Digital Negative (universal) |
JPEG Formats
Standard JPEG files are copied only when no matching RAW exists:
How It Works
phopy follows an opinionated workflow designed for photographers who shoot RAW+JPEG:
- Scan: phopy walks through the source directory and identifies all RAW and JPEG files
- Filter: Files are filtered based on date range (if specified) using EXIF metadata
- Match: JPEGs are checked for matching RAW files (same base filename)
- Plan: A copy plan is generated showing what will be copied
- Execute: Files are copied with progress feedback
RAW/JPEG Handling
The core feature of phopy is intelligent RAW/JPEG handling:
- RAW files are always copied โ These are your primary image files
- JPEGs are only copied when no matching RAW exists โ This handles cases like HDR, panoramas, or in-camera edits where the camera only produces a JPEG
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:
IMG_001.ARWIMG_002.ARWIMG_003.JPGHDR_001.JPG
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:
- Without
--override: Existing files are automatically skipped - With
--override: You'll be prompted to confirm overwriting existing files
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:
--from 2024-06-15โ Include photos from June 15, 2024 at 00:00:00 onwards--until 2024-06-15โ Include photos up to June 15, 2024 at 23:59:59 (inclusive)
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