Carl O'Beirne
Carl O'Beirne

Reputation: 329

Get the date a file was created, create a folder with that date and move the files

I'm trying to automate organizing my photography folder of over 3000 photos.

I'd like to get the date the file was created, create a new folder of that date formatted as DD-MM-YYYY and move the file from its current folder into the new folder.

I was able to retrieve the created date of one of the files using the below code

print("created: %s" % time.ctime(os.path.getctime(file)))

Which returns created: Fri Mar 22 17:49:36 2019.

Below is a sample of the folder. In this case, the created date is the same as the modified date but this is not always the case!

Files in folder

How can I achieve this?

Upvotes: 3

Views: 3797

Answers (2)

jorop
jorop

Reputation: 523

You can use mtime instead of ctime but as it looks from your screenshot and as far as I know, there is no way to get the 'time created' time on windows. ctime stands for change time and is more subject to changes than mtime. (Detailed explaination here)

What you can do in order to get to your goal, is read out the EXIF-data from your images. They should hold the date and time when your images were taken. If you are unsure, if your images hold EXIF-data, you can use the following script to fall back to mtime, if no exif-data is found:

import exifread
import shutil
import os
import sys
import datetime

ALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg', 'cr2'])

def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

if len(sys.argv) < 1:
    print('Please provide directory as argument!')

directory = sys.argv[1] # get the directory where we are looking for images
img_files = os.listdir(directory)  # get the files of the directory

for img in img_files:
    date = None
    if allowed_file(img): # check if the file is an image file
        full_path = os.path.join(directory, img)
        with open(full_path, 'rb') as image_file:
            tags = exifread.process_file(image_file, stop_tag='EXIF DateTimeOriginal')
            date_taken = str(tags.get('EXIF DateTimeOriginal'))
            try:
                date_time_obj = datetime.datetime.strptime(date_taken, '%Y:%m:%d %H:%M:%S')
                date = date_time_obj.date() # getting the date in YYYY-MM-DD format
            except ValueError:
                print('Cannot find EXIF')
        if not date:
            print('Using mtime')
            mtime = os.path.getmtime(full_path)
            date_time_obj = datetime.datetime.fromtimestamp(mtime)
            date = date_time_obj.date()
        print('Image: {} - Date: {}'.format(img, date))
        new_directory = 'Sorted/{}'.format(date)
        os.makedirs(new_directory, exist_ok=True)  # make the new directory
        shutil.copyfile(full_path, os.path.join(new_directory, img))  # copy file into the new directory - it will have the format YYYY-MM-DD

This script will read out EXIF data from your images, if there is none, it falls back to mtime, creates folders and copies the images into the folders.

Please note that in this script I formatted the date to YYYY-MM-DD. You can change it of course easily. It's just, that the directories in the Sorted-folder than are displayed in ascending order, which is convinient. But of course not mandatory.

If you safe the script as sort.py you can start it with python sort.py <directory-to-sort>. (exifread and shutil must be installed via pip install before that)

Upvotes: 2

ggorlen
ggorlen

Reputation: 56885

You can use os.listdir to get a list of files in a directory, then filter them by os.path.isfile and/or f.endswith to only accept image files. You pretty much have the timestamp code (you can use strftime to format it), so it's a matter of making any necessary directories with os.makedirs and copying the files with os.replace.

All relevant methods can be found in the documentation for the os and datetime modules.

import os
from datetime import datetime

path = "."
ext = "CR2"

for f in os.listdir(path):
    fpath = os.path.join(path, f)

    if os.path.isfile(fpath) and fpath.endswith(ext):
        time = datetime.fromtimestamp(os.path.getctime(fpath)).strftime("%d-%m-%Y")
        os.makedirs(os.path.join(path, time), exist_ok=True)
        os.replace(fpath, os.path.join(path, time, f))

If you want to accept multiple extensions and organize them into subfolders by extension, you can use:

import os
from datetime import datetime

path = "foo"
exts = set(["cr2", "jpg"])

for f in os.listdir(path):
    fpath = os.path.join(path, f)
    ext = f.split(".")[-1].lower()

    if os.path.isfile(fpath) and ext in exts:
        time = datetime.fromtimestamp(os.path.getctime(fpath)).strftime("%d-%m-%Y")
        os.makedirs(os.path.join(path, time, ext), exist_ok=True)
        os.replace(fpath, os.path.join(path, time, ext, f))

Upvotes: 3

Related Questions