Created
July 24, 2025 14:52
-
-
Save kenilt/b7040547eb5e18704190f74b17bc5c1f to your computer and use it in GitHub Desktop.
Group media files (photos, videos, etc.) into folders by date. This is useful when you have thousands of mixed files exported from phones, cameras, or cloud services.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
import shutil | |
import re | |
from datetime import datetime | |
# Set your folder path | |
folder_path = "path/to/target/folder" | |
# Date patterns to extract from filenames | |
patterns = [ | |
r"_(\d{8})_", # _YYYYMMDD_ | |
r"_(\d{8})\d{6}", # _YYYYMMDDHHMMSS | |
r"(\d{8})_\d{6}" # YYYYMMDD_HHMMSS | |
] | |
# === Step 1: Move files to YYYY_MM_DD folders === | |
files = os.listdir(folder_path) | |
for file in files: | |
file_path = os.path.join(folder_path, file) | |
if file.startswith("._") or not os.path.isfile(file_path): | |
continue | |
# Try extracting date from known patterns | |
date_str = None | |
for pattern in patterns: | |
match = re.search(pattern, file) | |
if match: | |
date_str = match.group(1) | |
break | |
# Fallback: use last modified date | |
if not date_str: | |
mod_time = os.path.getmtime(file_path) | |
date_str = datetime.fromtimestamp(mod_time).strftime("%Y%m%d") | |
folder_name = f"{date_str[:4]}_{date_str[4:6]}_{date_str[6:8]}" | |
folder_full_path = os.path.join(folder_path, folder_name) | |
os.makedirs(folder_full_path, exist_ok=True) | |
shutil.move(file_path, os.path.join(folder_full_path, file)) | |
print(f"Moved {file} to {folder_name}/") | |
# === Step 2: Merge folders with < 3 files into YYYY_MM === | |
all_folders = [ | |
f for f in os.listdir(folder_path) | |
if os.path.isdir(os.path.join(folder_path, f)) and re.match(r"\d{4}_\d{2}_\d{2}", f) | |
] | |
all_folders.sort() | |
for folder in all_folders: | |
folder_path_full = os.path.join(folder_path, folder) | |
items = os.listdir(folder_path_full) | |
if len(items) < 3: | |
year_month = "_".join(folder.split("_")[:2]) | |
target_folder_path = os.path.join(folder_path, year_month) | |
os.makedirs(target_folder_path, exist_ok=True) | |
for item in items: | |
src = os.path.join(folder_path_full, item) | |
# 🔐 Skip macOS ghost/metadata files | |
if item.startswith("._") or not os.path.isfile(src): | |
continue | |
dst = os.path.join(target_folder_path, item) | |
shutil.move(src, dst) | |
print(f"Merged {item} from {folder}/ into {year_month}/") | |
os.rmdir(folder_path_full) | |
print(f"Removed empty folder {folder}/") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment