Search code examples
pythonstat

Iterate over all files in folder and subfolders and get creation date


I am trying to sort out my Photos folder and I thought I do it with Python. What I want to do is go through my folder, check the extension of each photo (or video) and move it to a new location according to its creation date. I got the idea from a video in YouTube. I also used this Now the following code works perfectly for one folder at a time:

from stat import S_ISREG, ST_CTIME, ST_MODE
import os, sys, time, shutil


dir_path = "F:/Yannis/TestSortingFrom"
info_dict = {}
file_type_dict = {
    'CR2' : 'CR2',
    'CR3' : 'CR3',
    'dng' : 'DNG',
    'jpg' : 'JPG',
    'jpeg' : 'JPG',
    'JPG' : 'JPG',
    'bmp' : 'IMAGES',
    'png' : 'IMAGES',
    'ico' : 'IMAGES',
    'MP4' : 'Video',
    'mp4' : 'Video',
    'avi' : 'Video',
    'mov' : 'Video',
    }
destination_path = "F:/Yannis/SortingDestination/"
year_exists = False
month_exists = False


data = (os.path.join(dir_path, fn) for fn in os.listdir(dir_path))
data = ((os.stat(path), path) for path in data)


data = ((stat[ST_CTIME], path)
           for stat, path in data if S_ISREG(stat[ST_MODE]))
for cdate, path in sorted(data):
    info_dict.update({os.path.basename(path): time.ctime(cdate) })
for key, value in info_dict.items():
    file_date = value.split()
    file_extension = key.split(".")
    for key2, value2 in file_type_dict.items():
        if file_extension[1] == key2:
            destination_folder = destination_path +value2
            for folder_name in os.listdir(destination_folder):
                if folder_name == file_date[4] :
                    destination_folder1 = destination_folder +'/' + folder_name
                    year_exists = True
                    for folder_month in os.listdir(destination_folder1):
                        if folder_month == file_date[1]:
                            destination_folder2 = destination_folder1 + '/' + folder_month
                            month_exists = True
                            FROM = dir_path + '/' + key
                            TO = destination_folder2 + '/' + key
                            shutil.move(FROM, TO)
            if not year_exists:
                os.mkdir(destination_path + value2 + '/' + file_date[4])
                destination_folder1 = destination_path + '/' + value2 + '/' + file_date[4]

            if not month_exists:
                os.mkdir(destination_path + value2 + '/' + file_date[4] + '/' + file_date[1])
                destination_folder2= destination_path + value2 + '/' + file_date[4] + '/' + 
                                     file_date[1]
                FROM = dir_path + '/' + key
                TO = destination_folder2 + '/' + key
                shutil.move(FROM, TO)

    destination_folder2 = destination_path + '/' + 'Uncategorized'
    FROM = dir_path + '/' + key
    TO = destination_folder2 + '/' + key
    shutil.move(FROM, TO)

I tried the following to iterate over the folder tree but it returns a FileNotFound Error.

for dirname, dirnames, filenames in os.walk('F:/Yannis/TestSortingFrom'):
        for subdirname in dirnames:
            dirpath = os.path.join(dirname, subdirname)

I replaced dir_path in the previous code with dirpath

Do you have any ideas? Because I am at a loss. I could do it one file at a time but I thing it could be great to simply specify a folder and be done with it.

The error message is the following:

Traceback (most recent call last):
File "C:\Users\Yannis\AppData\Local\Programs\Python\Python37\lib\shutil.py", line 566, in move os.rename(src, real_dst)
FileNotFoundError: [WinError 2] The system cannot find the file specified: 
'F:/Yannis/TestSortingFrom\\Camera/IMG_20110305_143031.jpg' -> 
'F:/Yannis/SortingDestination//Uncategorized/IMG_20110305_143031.jpg'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "G:/Python/PyCharmProjects/FileSorting/test.py", line 68, in <module> shutil.move(FROM, TO)
File "C:\Users\Yannis\AppData\Local\Programs\Python\Python37\lib\shutil.py", line 580, in move copy_function(src, real_dst)
File "C:\Users\Yannis\AppData\Local\Programs\Python\Python37\lib\shutil.py", line 266, in copy2 copyfile(src, dst, follow_symlinks=follow_symlinks)
File "C:\Users\Yannis\AppData\Local\Programs\Python\Python37\lib\shutil.py", line 120, in copyfile with open(src, 'rb') as fsrc:
FileNotFoundError: [Errno 2] No such file or directory: 
'F:/Yannis/TestSortingFrom\\Camera/IMG_20110305_143031.jpg'

EDIT: Now the following code works (sort of). The weird thing is that if my origin_path has sub-directories then the program moves the files from the first sub-directory and leaves the others intact. If I run it a second time it moves the files from the second sub-directory and so on. Another strange behavior is that if different types of files (in my situation, .jpg, .JPG, .dng, .mp4) are in the same sub-directory, the program moves all the files except .mp4. If I run it a second time it moves the .mp4 too. The revised code is:

from pathlib import Path
import os, time, shutil
from stat import S_ISREG, ST_CTIME, ST_MODE


class fileToMove():
    def __init__(self, name, folder, date):
        self.name = name
        self.folder = folder
        self.date = date


info_list = []
info_dict = {}
file_type_dict = dict(CR2 = 'CR2', CR3 = 'CR3', dng = 'DNG', jpg = 'JPG',     jpeg = 'JPG', JPG = 'JPG', bmp = 'IMAGES',
                  png = 'IMAGES', ico = 'IMAGES', mp4 = 'Video', MP4 = 'Video', avi = 'Video', mov = 'Video')
destination_path = Path("F:/Yannis/SortingDestination/")
origin_path = Path('F:/Yannis/TestSortingFrom/')
year_exists = False
month_exists = False

for dirname, dirnames, filenames in os.walk(origin_path):
    for subdirname in dirnames:
        dirpath = os.path.join(dirname, subdirname)
        data = (os.path.join(dirpath, fn) for fn in os.listdir(dirpath))
        data = ((os.stat(path), path) for path in data)
        data = ((stat[ST_CTIME], path) for stat, path in data if S_ISREG(stat[ST_MODE]))
        for cdate, path in sorted(data):
            fl = fileToMove(os.path.basename(path), path, time.ctime(cdate))
            info_list.append(fl)
for filez in info_list:
    file_date = str(filez.date).split()
    file_name = str(filez.name).split('.')
    file_folder = str(filez.folder)
    print(filez.date, filez.folder, filez.name, file_name)
    for key, value in file_type_dict.items():
        if key == file_name[1]:
                destination_folder = destination_path / value
                for folder_name in os.listdir(destination_folder):
                    if folder_name == file_date[4]:
                        destination_folder1 = destination_folder / folder_name
                        year_exists = True
                        for folder_month in os.listdir(destination_folder1):
                            if folder_month == file_date[1]:
                                month_exists = True
                                FROM = file_folder
                                TO = destination_folder1 / folder_month / filez.name
                                shutil.move(FROM, TO)
                if not year_exists:
                    os.mkdir(destination_path / value / file_date[4])
                if not month_exists:
                    os.mkdir(destination_path / value / file_date[4] / file_date[1])
                    destination_folder2 = destination_path / value / file_date[4] / file_date[1]
                    FROM = file_folder
                    TO = destination_folder2 / filez.name
                    shutil.move(FROM, TO)

Solution

  • from pathlib import Path
    import os, time, shutil
    from stat import S_ISREG, ST_CTIME, ST_MODE
    
    
    class fileToMove():
        def __init__(self, name, folder, date):
            self.name = name
            self.folder = folder
            self.date = date
    
    info_list = []
    info_dict = {}
    file_type_dict = dict(CR2 = 'CR2', CR3 = 'CR3', dng = 'DNG', jpg = 'JPG', jpeg = 'JPG', JPG = 'JPG', bmp = 'IMAGES',
                      png = 'IMAGES', ico = 'IMAGES', mp4 = 'Video', MP4 = 'Video', avi = 'Video', mov = 'Video')
    destination_path = Path("F:/Yannis/SortingDestination/")
    origin_path = Path('F:/Yannis/Photos/2019/9-2-2019/')
    
    for dirname, dirnames, filenames in os.walk(origin_path):
        for subdirname in dirnames:
            dirpath = os.path.join(dirname, subdirname)
            data = (os.path.join(dirpath, fn) for fn in os.listdir(dirpath))
            data = ((os.stat(path), path) for path in data)
            data = ((stat[ST_CTIME], path) for stat, path in data if S_ISREG(stat[ST_MODE]))
            for cdate, path in sorted(data):
                fl = fileToMove(os.path.basename(path), path, time.ctime(cdate))
                info_list.append(fl)
                print(fl.date)
    for filez in info_list:
        file_date = str(filez.date).split()
        file_name = str(filez.name).split('.')
        file_folder = str(filez.folder)
        if file_name[1] not in file_type_dict:
            destination_folder3 = destination_path / 'Uncategorized'
            FROM = file_folder
            TO = destination_folder3 / filez.name
            shutil.move(FROM, TO)
        else:
            for key, value in file_type_dict.items():
                if key == file_name[1]:
                    year_exists = False
                    month_exists = False
                    day_exists = False
                    destination_folder = destination_path / value
                    for folder_year in os.listdir(destination_folder):
                        if folder_year == file_date[4]:
                            destination_folder_year = destination_folder / folder_year
                            year_exists = True
                            for folder_month in os.listdir(destination_folder_year):
                                if folder_month == file_date[1]:
                                    destination_folder_month = destination_folder_year / folder_month
                                    month_exists = True
                                    for folder_day in os.listdir(destination_folder_month):
                                        if folder_day == file_date[2]:
                                            day_exists = True
                                            FROM = file_folder
                                            TO = destination_folder_year / folder_month / folder_day / filez.name
                                            shutil.move(FROM, TO)
                    if not year_exists:
                        os.mkdir(destination_path / value / file_date[4])
                    if not month_exists:
                        os.mkdir(destination_path / value / file_date[4] / file_date[1])
                    if not day_exists:
                        os.mkdir(destination_path / value / file_date[4] / file_date[1] / file_date[2])
                        destination_folder2 = destination_path / value / file_date[4] / file_date[1] /file_date[2]
                        FROM = file_folder
                        TO = destination_folder2 / filez.name
                        shutil.move(FROM, TO)