An advanced media organization tool for users who need duplicate detection, stricter matching, and more controllable archiving workflows.
The program reads image EXIF time first. If EXIF time is unavailable, it falls back to the file's modified time.
Organized files are placed into the target directory using a year\month\day folder structure.
It supports:
- date-based folder organization
- move or copy modes
- perceptual duplicate detection for similar images
- strict SHA-256 duplicate detection for exact file matches
- multilingual CLI messages
- per-run log output for traceability
Language navigation:
- English: README.md
- 中文: README_zh.md
- 日本語: README_ja.md
This project is intended for advanced usage.
Compared with a basic date-based organizer, it adds:
- duplicate detection
- strict exact-file matching
- perceptual image matching with threshold control
- persistent hash database
- stronger destination safety rules
- automated smoke tests
If you only need simple date-based sorting with minimal complexity, a basic organizer may be a better fit.
- Recursively scans subfolders in the source directory
- Organizes images and videos by date automatically
- Uses
movemode by default - Supports
copymode to keep original files - Supports duplicate detection: off, perceptual image matching (
phash), or strict file matching (SHA-256) - Supports Chinese, English, and Japanese UI
- Generates a separate log file for each run
- Automatically appends a numeric suffix for duplicate file names
- Renames detected duplicates as
kept_name_dupN.extso they stay grouped in the archive - Generates
duplicate_report.csvfor duplicate traceability
.jpg.jpeg.png.mp4.mov
- Windows 10 or Windows 11
- Python 3.10 or later
- Dependency:
Pillow,exifread,pywin32(Windows only)
Install dependency:
.\venv\Scripts\python.exe -m pip install Pillow exifread pywin32Notes:
- It is recommended to create the virtual environment first with
python -m venv venvfrom the project root - The project virtual environment is typically located at
.\venv - Prefer
.\venv\Scripts\python.exeand.\venv\Scripts\pip.exeso you always know where dependencies are being installed - If you run plain
pythonorpip, you may accidentally use the global Python installation or another virtual environment
For detailed environment setup, see:
Enter the project root first, then run the command:
cd D:\ImageOrganizerRecommended command:
.\venv\Scripts\python.exe .\main.py --src SOURCE_DIR --dst TARGET_DIRExample:
.\venv\Scripts\python.exe .\main.py --src D:\InputPhotos --dst D:\SortedPhotosSource directory. Required.
Destination directory. Required.
Organization mode:
move: move files, defaultcopy: copy files and keep originals
Example:
.\venv\Scripts\python.exe .\main.py --src D:\InputPhotos --dst D:\SortedPhotos --mode copyInterface language:
zh: Chineseen: Englishja: Japanese
Example:
.\venv\Scripts\python.exe .\main.py --src D:\InputPhotos --dst D:\SortedPhotos --lang en
.\venv\Scripts\python.exe .\main.py --src D:\InputPhotos --dst D:\SortedPhotos --lang jaDuplicate detection mode:
off: disable duplicate detectionphash: detect visually similar images with perceptual hashstrict: detect exact file matches with SHA-256
Notes:
phashis suitable for visually similar imagesstrictis for exact-match users who only want byte-identical files treated as duplicateshash_dbis only used as a hint inside the current destination root and will not redirect files into old destination folders- Detected duplicates are still copied or moved into the normal dated archive folder
- Duplicate files are renamed based on the first retained file name, such as
photo_dup1.jpgandphoto_dup2.jpg - Each run appends duplicate reference rows to
duplicate_report.csvin the same folder as the run log
Example:
.\venv\Scripts\python.exe .\main.py --src D:\InputPhotos --dst D:\SortedPhotos --duplicate-detection off
.\venv\Scripts\python.exe .\main.py --src D:\InputPhotos --dst D:\SortedPhotos --duplicate-detection strictSets the maximum Hamming distance for perceptual hash matching. The default is 4.
Notes:
- Lower values are stricter
- Higher values make similar images more likely to be treated as duplicates
- This option only applies when
--duplicate-detection phashis used
Example:
.\venv\Scripts\python.exe .\main.py --src D:\InputPhotos --dst D:\SortedPhotos --duplicate-detection phash --phash-threshold 4.\venv\Scripts\python.exe .\main.py --src D:\InputPhotos --dst D:\SortedPhotos.\venv\Scripts\python.exe .\main.py --src D:\InputPhotos --dst D:\SortedPhotos --mode copy.\venv\Scripts\python.exe .\main.py --src D:\InputPhotos --dst D:\SortedPhotos --lang en.\venv\Scripts\python.exe .\main.py --src D:\InputPhotos --dst D:\SortedPhotos --lang ja.\venv\Scripts\python.exe .\main.py --src D:\InputPhotos --dst D:\SortedPhotos --duplicate-detection strict.\venv\Scripts\python.exe .\main.py --src D:\InputPhotos --dst D:\SortedPhotos --duplicate-detection phash --phash-threshold 4The program automatically creates or reuses the log folder under the script directory.
Log file names use this format:
organize_log_YYYYMMDD_HHMMSS.txt
Example:
organize_log_20260413_135222.txt
After execution, the program prints the full path of the generated log file.
When duplicates are detected, the program also appends records to:
duplicate_report.csv
The report is created in the same folder as the run log and currently includes:
original_nameoriginal_pathkept_pathduplicate_methodhashduplicate_path
- Recursively scans all subfolders in the source directory
- Uses image EXIF time first
- Falls back to file modified time when EXIF is unavailable
- Outputs files to
target\year\month\day\ - When duplicate detection is enabled, only records inside the current destination root are used as matches
- Adds a numeric suffix if a file with the same name already exists
- Duplicate files are still placed into the normal dated archive folder
- Duplicate files are renamed from the retained file name using
_dupN
Duplicate name example:
photo.jpg
photo_1.jpg
photo_2.jpg
Duplicate detection naming example:
photo.jpg
photo_dup1.jpg
photo_dup2.jpg
main.pyProgram entry pointcore/Date detection and EXIF reading logicservices/File organization logiclocales/Chinese, English, and Japanese UI textslog/Log output folder for each run
- Make sure the source and destination paths are correct
- Default
movemode removes files from the source directory - Use
--mode copyif you need to keep original files - It is recommended to test with a small number of files first
- Back up important files before large batch processing
- File is in use and cannot be moved or copied
- File permission is insufficient
- Image EXIF data is invalid
- Destination directory is not writable
This tool is intended to automatically organize image and video files. In actual use, the result may still differ from expectations due to incorrect paths, permission problems, file locks, disk issues, invalid time metadata, interrupted execution, or other unforeseen factors.
Please note:
- Default
movemode moves original files - Duplicate file names are automatically renamed
- If EXIF time or file time is inaccurate, the destination date folder may not match the real capture date
- Logs are only for assistance and do not guarantee completeness of results
To reduce risk:
- Test with a small set of files first
- Prefer
--mode copyfor verification - Back up important data before full processing
- Check both the log and destination folders after execution
For the full disclaimer, see: