A photo organizer for travelers
A Python tool to organize photo libraries by extracting EXIF metadata (GPS, dates, camera) and creating trip-based albums by moving files into organized folders.
- EXIF Metadata Extraction: Extract GPS coordinates, dates, camera info from photos
- GPS-based Trip Detection: Identify countries and cities using a database of 80+ cities worldwide
- Smart Trip Grouping: Automatically detect multi-country trips (gap ≤ 3 days between countries)
- Album Organization: Move files into
YEAR - CountryorYEAR - TripNamefolders - Audit System: Verify album classification accuracy
- README Generation: Auto-generate album READMEs with Unsplash city images
# macOS
brew install exiftool
# Ubuntu/Debian
sudo apt-get install libimage-exiftool-perl
# Python 3.x (usually pre-installed)
python3 --versiongit clone https://github.com/KnHack/wanderlens.git
cd wanderlens
# Edit configuration in photo_organizer.py
# Set PICTURES_BASE and ALBUMS_DIR to your paths# 1. Analyze photos and extract EXIF metadata
python3 photo_organizer.py analyze "Camera Roll/2024"
# 2. Review GPS locations
python3 photo_organizer.py locations analysis_results/metadata_*.json
# 3. Create albums (moves files)
python3 photo_organizer.py create analysis_results/metadata_*.json
# 4. Audit albums (REQUIRED - verify classification)
python3 photo_organizer.py audit
# 5. Suggest trip groupings
python3 photo_organizer.py suggest-groups
# 6. Merge multi-country trips
python3 photo_organizer.py merge "2024 - Asia" "2024 - Japan" "2024 - South Korea"
# 7. Generate READMEs
python3 photo_organizer.py readme| Command | Description |
|---|---|
analyze <folder> |
Extract EXIF metadata from photos to JSON |
locations <json> |
Analyze GPS locations and show country distribution |
create <json> |
Create album folders and move files |
audit |
Verify year and country match for all albums |
suggest-groups |
Identify trips that can be merged (gap ≤ 3 days) |
merge <trip> <albums...> |
Merge multiple country albums into one trip |
readme [album] |
Generate README files for albums |
# Dry run (preview without making changes)
python3 photo_organizer.py analyze "Camera Roll/2024" --dry-run
python3 photo_organizer.py create metadata.json --dry-run
# Process specific album
python3 photo_organizer.py readme "2024 - Japan"Edit the constants at the top of photo_organizer.py:
# Base paths
PICTURES_BASE = "/path/to/your/Pictures"
ALBUMS_DIR = f"{PICTURES_BASE}/Albums"
# Trip grouping
MAX_GAP_DAYS = 3 # Maximum days between countries to consider same trip
# Minimum photos for album creation
MIN_PHOTOS_FOR_ALBUM = 5The tool automatically detects multi-country trips based on date proximity:
Grouping Logic:
- If gap between end of Country A and start of Country B is ≤ 3 days → Same trip
- Use descriptive names: "Eurotrip", "Asia", "Morocco & Portugal"
Examples:
2018 - Eurotrip = France (Aug 7-8) + Italy (Aug 12-16) + Greece (Aug 17-19) + Spain (Aug 21-27)
2024 - Asia = Japan (Mar 17 - Apr 2) + South Korea (Apr 4-8)
2025 - Morocco & Portugal = Morocco (Aug 7-14) + Portugal (Aug 16-24)
Do NOT group:
- Trips with gaps > 3 days between countries
- Residence albums ("Life in X")
- Countries from same year but different months
Albums/
├── 2024 - Asia/ # Multi-country trip [JP, KR]
│ ├── metadata.json # Album metadata with summary
│ ├── README.md # Auto-generated with city images
│ └── *.jpg, *.dng, *.mov # Photo/video files
├── 2024 - Germany/ # Single country trip
├── 2024 - Life in Austria/ # Residence album
├── WithoutGPSInfo-2024/ # Photos without GPS data
└── README.md # Main index
The tool uses a database of 80+ cities for accurate country detection:
CITIES_GPS = {
# Asia
(35.68, 139.69): ("Tokyo", "Japan"),
(35.01, 135.77): ("Kyoto", "Japan"),
(37.57, 126.98): ("Seoul", "South Korea"),
# Europe
(48.86, 2.35): ("Paris", "France"),
(41.90, 12.50): ("Rome", "Italy"),
(52.52, 13.41): ("Berlin", "Germany"),
# Americas
(40.71, -74.01): ("New York", "USA"),
(-23.55, -46.64): ("Sao Paulo", "Brazil"),
(-34.60, -58.38): ("Buenos Aires", "Argentina"),
# ... 80+ more cities
}Falls back to country bounding boxes when no city match is found.
Important: The tool prioritizes filename date over EXIF metadata because camera dates can be misconfigured.
# Supported filename patterns
YYYYMMDD_HHMMSS.jpg # Android
IMG_YYYYMMDD_HHMMSS.jpg # iOS/Samsung
20240703_083732345_iOS.dngDate Source Hierarchy:
- Filename (most reliable)
- FileModifyDate
- DateTimeOriginal (can be wrong)
- CreateDate
Auto-generated READMEs include:
- Country flag emoji and trip name
- Date range
- File type distribution (DNG, MOV, JPG, etc.)
- Cities visited with photo counts
- Unsplash images for each city
- Camera models used
- Date distribution
Example:
# 🇯🇵 2024 - Japan
📅 **Dates:** 17 March 2024 → 02 April 2024
📁 **Total files:** 577
## 🗺️ Places Visited
### 🗼 Tokyo (326 photos)

### ⛩️ Kyoto (75 photos)
These countries are geographically close. Use the city database:
- Berat (40.7, 19.95) → Albania
- Kotor (42.42, 18.77) → Montenegro
Long shared border causes confusion:
- Las Leñas (-35.1, -70.1) → Argentina (ski resort near Chile)
Some cameras have incorrect date settings (e.g., 2002). Always use filename date.
1. analyze → Extract EXIF metadata to JSON
2. locations → Review country distribution
3. create → Create album folders and move files
4. audit → ⚠️ VERIFY classification (required!)
5. fix → Move any misclassified files
6. suggest-groups → Identify trips to merge
7. merge → Combine consecutive country albums
8. readme → Generate album READMEs
Always run audit after creating albums to catch classification errors.
- Files may show 0 bytes locally until accessed
exiftooltriggers download when reading metadata- Processing speed: ~1 file/second
- Full year: 15-30 minutes depending on file count
If analysis produces JSON with null entries:
import json
with open('file.json', 'r') as f:
content = f.read()
content = content.replace('}\nnull\n,', '},')
data = json.loads(content)
with open('file.json', 'w') as f:
json.dump(data, f, indent=2)wanderlens/
├── photo_organizer.py # Main unified script
├── generate_album_readme.py # README generator with city images
├── README.md # This file
├── LESSONS_LEARNED.md # Common errors and solutions
└── analysis_results/ # Cached EXIF metadata (gitignored)
- Fork the repository
- Create a feature branch
- Add cities to
CITIES_GPSif needed - Submit a pull request
MIT License - See LICENSE file for details.