Use Case
/
Personal Task Automation
Create custom scripts and tools to streamline routine tasks and increase efficiency
Model
•
Claude 3.7 Sonnet
Write a cross-platform Python script that scans my Downloads folder every hour and automatically renames and moves image files into date-stamped subfolders.
Automatic Image File Organizer
Here's a cross-platform Python script that scans your Downloads folder every hour, identifies image files, and organizes them into date-stamped subfolders based on their creation/modification dates:
1import os
2import shutil
3import time
4import datetime
5import schedule
6import platform
7import logging
8from pathlib import Path
9from PIL import Image
10from PIL.ExifTags import TAGS
11
12# Set up logging
13logging.basicConfig(
14 level=logging.INFO,
15 format='%(asctime)s - %(levelname)s - %(message)s',
16 handlers=[
17 logging.FileHandler("image_organizer.log"),
18 logging.StreamHandler()
19 ]
20)
21
22def get_downloads_folder():
23 """Get the downloads folder path based on the operating system"""
24 if platform.system() == "Windows":
25 return os.path.join(os.path.expanduser("~"), "Downloads")
26 elif platform.system() == "Darwin": # macOS
27 return os.path.join(os.path.expanduser("~"), "Downloads")
28 else: # Linux and other Unix-like
29 return os.path.join(os.path.expanduser("~"), "Downloads")
30
31def get_image_date(file_path):
32 """Extract date from image metadata or use file modification date"""
33 try:
34 # Try to get date from EXIF data
35 with Image.open(file_path) as img:
36 exif_data = img._getexif()
37 if exif_data:
38 for tag_id, value in exif_data.items():
39 tag = TAGS.get(tag_id, tag_id)
40 if tag == "DateTimeOriginal":
41 # Parse the date string (format: YYYY:MM:DD HH:MM:SS)
42 date_str = value.split()[0].replace(":", "-")
43 return date_str
44 except (AttributeError, KeyError, IndexError, TypeError, OSError):
45 pass
46
47 # Fall back to file modification time
48 mod_time = os.path.getmtime(file_path)
49 date_str = datetime.datetime.fromtimestamp(mod_time).strftime('%Y-%m-%d')
50 return date_str
51
52def is_image_file(file_path):
53 """Check if the file is an image based on extension"""
54 image_extensions = {'.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tiff', '.webp', '.heic'}
55 return os.path.splitext(file_path.lower())[1] in image_extensions
56
57def organize_images():
58 """Scan downloads folder and organize images into date-based folders"""
59 downloads_folder = get_downloads_folder()
60 logging.info(f"Scanning {downloads_folder} for images...")
61
62 # Create a base folder for organized images
63 organized_folder = os.path.join(downloads_folder, "Organized_Images")
64 if not os.path.exists(organized_folder):
65 os.makedirs(organized_folder)
66
67 # Get all files in downloads folder
68 files = [f for f in os.listdir(downloads_folder) if os.path.isfile(os.path.join(downloads_folder, f))]
69
70 # Counter for renamed files
71 moved_count = 0
72
73 for file_name in files:
74 file_path = os.path.join(downloads_folder, file_name)
75
76 # Skip the script itself and non-image files
77 if not is_image_file(file_path):
78 continue
79
80 try:
81 # Get date from image
82 date_str = get_image_date(file_path)
83
84 # Create date folder if it doesn't exist
85 date_folder = os.path.join(organized_folder, date_str)
86 if not os.path.exists(date_folder):
87 os.makedirs(date_folder)
88
89 # Generate a unique name for the file
90 file_ext = os.path.splitext(file_name)[1]
91 new_file_name = f"{date_str}_{int(time.time())}_{moved_count}{file_ext}"
92 new_file_path = os.path.join(date_folder, new_file_name)
93
94 # Move and rename the file
95 shutil.move(file_path, new_file_path)
96 logging.info(f"Moved: {file_name} -> {new_file_path}")
97 moved_count += 1
98
99 except Exception as e:
100 logging.error(f"Error processing {file_name}: {str(e)}")
101
102 logging.info(f"Organized {moved_count} images")
103
104def main():
105 """Main function to schedule and run the image organization task"""
106 logging.info("Image Organizer started")
107
108 # Run once at startup
109 organize_images()
110
111 # Schedule to run every hour
112 schedule.every(1).hour.do(organize_images)
113
114 # Keep the script running
115 while True:
116 schedule.run_pending()
117 time.sleep(60) # Check every minute
118
119if __name__ == "__main__":
120 main()
How to Use This Script
- Install required packages:
1pip install pillow schedule
- Run the script:
- It will automatically detect your Downloads folder based on your operating system
- Images will be organized into a folder called "Organized_Images" within your Downloads folder
- Each image will be placed in a subfolder named with its creation date (YYYY-MM-DD)
- Images will be renamed with the pattern: DATE_TIMESTAMP_COUNTER.extension
- Features:
- Cross-platform (works on Windows, macOS, and Linux)
- Uses EXIF data when available to determine the image date
- Falls back to file modification date when EXIF data isn't available
- Logs all actions to both console and a log file
- Runs once when started and then every hour afterward
- Handles errors gracefully
- To run the script in the background:
- On Windows: Create a scheduled task
- On macOS/Linux: Use cron jobs or create a service
The script will continue running until you stop it, checking your Downloads folder every hour and organizing any new image files.
Explore Related Use Cases
Experience Ninja's AI Assistant
Try for free today. Plans starting at $5/month.