A command-line tool and standalone web server for importing, renaming, and rotating photos and videos from cameras, USB drives, and memory cards.
- Scans directories for media files (images, video, audio)
- Detects capture time via EXIF metadata, filename patterns, or file attributes
- Organises files into a configurable date-based directory hierarchy
- Renames files according to capture timestamp
- Performs lossless JPEG rotation (via exiftran or jpegtran)
- Supports dry-run mode for previewing changes without modifying files
- Standalone web server for use on headless machines (e.g. a home server or Raspberry Pi)
- Detects mounted removable storage by path mask
- Provides one-click mount, import, and unmount via a browser interface
- Same import pipeline as the CLI tool
- Python 3.6+
| Platform | Support |
|---|---|
| Debian-based Linux | Full (CLI + Web) |
| Other Linux | Unofficial (likely works) |
| Windows 7+ | CLI + Web |
| macOS (with Homebrew) | CLI only |
| Dependency | Purpose |
|---|---|
| exiftool | EXIF metadata reading |
| exiftran or jpegtran | Lossless JPEG rotation |
| pmount | Storage mount/unmount (server only) |
- PyExifTool
- progressbar
- psutil
- pypiwin32 (Windows only)
sudo apt install exiftran exiftool pmount pip
sudo pip install photo-importerdebuild -b
sudo apt install pip python3-exif python3-progressbar exiftran python3-psutil
sudo pip install PyExifTool
sudo dpkg -i ../photo-importer_*.debsudo apt install exiftran exiftool pmount pip
sudo pip install PyExifTool progressbar psutil
sudo python3 ./setup.py install- Download and install Python 3
- Download and install ExifTool
- Download and extract jpegtran into the
photo_importerfolder - Install the package and its Windows dependencies:
python -m pip install pypiwin32 photo-importerIn-place processing — rename and rotate files without moving them:
photo-importer /path/to/media/filesImport to output directory — move (or copy) files into a date-based hierarchy:
photo-importer /path/to/media/files /output/pathFiles are moved by default. To copy instead, set move_mode = 0 in the config file.
CLI options:
| Option | Description |
|---|---|
in_path |
Source directory to scan (required) |
out_path |
Destination directory (optional; in-place mode if omitted) |
-c, --config FILE |
Path to a custom config file |
-l, --logfile FILE |
Log file path (default: log.txt) |
-d, --dryrun |
Dry run — preview actions without modifying files |
- Attach a USB drive or insert a memory card
- Open
http://<hostname>:8080in a browser - Click Mount
- Click Import
- Click Unmount
cd photo_importer
python run.py -c ..\photo-importer-win.cfg path\to\media\files \output\pathphoto-importer-server.bat| Scope | Default config file |
|---|---|
| CLI tool | ~/.photo-importer.cfg |
| Web server | /etc/photo-importer.cfg |
A custom config file can be passed to the CLI with the -c option.
All available options are documented with comments inside the config file itself.
Thanks to everyone who tested the tool and provided feedback.
Bug reports, suggestions, and pull requests are welcome!
Give a ⭐️ if this project helped you!


