Как разложить фото, видео по папкам, исходя из их дат, используя python

  • Tutorial


Всем знакомы завалы из фото и видео, кои покоятся годами после копирования с устройств.

Особенно это характерно для iphone,ipad, которые при прямом копировании (без itunes) создают
залежи медиаконтента. Как это все разложить по годам-месяцам?

Да, есть синхронизация, да, можно сразу все сортировать. Но…

Кто-то предпочитает ничего не трогать, так как соблюдается единство свалки, кто-то делает робкие попытки разложить все накопленное хотя бы по годам.

Бесспорно, через проводник, используя табличный вид, вручную не составит труда все это это раскидать, но начинаешь смотреть старые фото, и процесс затягивается.

Поэтому напишем простую программу, которая разложит файлы в папке по годам с месяцами в них:





Программа сама будет определять дату, «заглядывая» в дату изменения файла:



Почему используем дату изменения, а не дату создания файла?
Как правило, она более корректно указывает на дату файла, чем ее тезка.

Импорт модулей на старте:
import os,time
import datetime
import shutil

Предложим пользователю скопировать путь (windows) к папке с файлами:

p=input('Скопируйте сюда путь к фото. Например: E:/\1')
os.chdir(p)

Введем функцию создания папок с месяцами от 01 до 12 (да простят мне отсутствие f' строк):

#создаем папки месяцев от 01 до 12
def d():
    for x in range (1,13):
        if x>9:
            if not os.path.exists(str(x)):
                os.makedirs(str(x))
        else:
            if not os.path.exists('0'+str(x)):
                os.makedirs('0'+str(x))

Следующая функция обработает дату, полученную с фото/видео файла:

def mod_date(file):
    t = os.path.getmtime(file)
    return datetime.datetime.fromtimestamp(t)

Теперь, пройдясь по папке, программа соберет все расширения файлов, а заодно,
определит какой год у файла. Для каждого года будет создана своя папка, а в ней,
в свою очередь, будут созданы папки с месяцами:

a=[] #['AAE', 'MOV', 'JPG', 'PNG']
for root, dirs, files in os.walk(p):    
    for file in files:
        if file[-3:] not in a:
            a.append(file[-3:])
        if file[-3:] in a:
            year=str(mod_date(file))[:10][:4]            
            if not os.path.exists(year):
                os.makedirs(year)
            os.chdir(p+'/'+year)            
            d()
            os.chdir(p)

*Таким образом можно раскидать по папкам файлы с совершенно разными (любыми) расширениями, а не только jpeg,mov,mkv.

Еще раз пройдемся по папке со свалкой фото, теперь уже перенося фото в соответствующие, вновь созданные папки:

try:
    for root, dirs, files in os.walk(p):    
        for file in files:
                if file[-3:] in a:
                    year=str(mod_date(file))[:10][:4]                    
                    month=str(mod_date(file))[:10][5:7] #месяц создания фото
                    shutil.move(file, year+'/'+month+'/'+file) #перенос файла в папку
except EnvironmentError:
    ('Вроде готово')

Так как программа завершается с ошибкой, в цикле не найдя последнего файла, что не влияет на ее корректное выполнение, используется костыль из try,except, который притупляет бдительность впечатлительных особ, получающих красноту в консоль.

P.S.: Пост не претендует на научность, но, возможно, кому-то поможет победить свалки фото/видео.

Программа — скачать.

Similar posts

Ads
AdBlock has stolen the banner, but banners are not teeth — they will be back

More

Comments 18

    0
    Отличная практика для начинающих.
      0
      Как практикум по языку — хорошо. Но подобная задача прекрасно решается групповым переименованием в Total Commander.
        0
        Благодарю.
        Попробую сегодня на многолетнем архиве фотографий.
          0
          Всё отлично, только дату лучше брать из Exif.Image.DateTime

          from PIL import Image
          def get_date_taken(path):
              return Image.open(path)._getexif()[36867]
            0
            Интересная штука. Еще бы по не системным свойствам научиться раскладывать
              0
              Если Вы про раскладывание по тому что изображено на снимках, то Вам в сторону TensorFlow надо смотреть.
              +1
              мне кажется, что на нормальном шелле (bash/zsh и прочие) такое делается в пару строк
                0

                Это только под Windows работает?

                  0
                  С небольшими изменениями должно поехать и на Linux.
                  +1

                  Ужас.
                  '/' заменить на os.path.sep
                  а ещё лучше прочитать про os.path.join()

                  +2

                  Расширение файла это не всегда последние три символа, есть специальная функция для этого — os.path.splitext. Зачем нужно два прохода и пустые папки по месяцам — не ясно.

                    0

                    Стоит опубликовать исходники на GitHub :)

                      0
                      тут прямо есть что улучшать в коде…
                      из того что еще не упомянули заметил отсутствие lower() или upper() для расширения файла (сравнивать все желательно в одном регистре)
                      ну и os.chdir(p) — прям не нужно использовать, здесь проще сформировать путь куда сохранять и делать shutil.move
                      вместо функции d для папок месяцев правильнее формировать путь сохранения с использованием '{0:02d}'.format(x) где x — месяц от 1 до 12

                      Просто для такой задачи вся элегантность и простота питона не видна, все можно сделать сильно проще и короче

                        0
                        Благодарю. Код не идеален бесспорно. Всего лишь лопатка для разгребания )
                          0
                          так разгребать красиво можно
                          for i in range(1, 13):
                              ... if os.path.exists(f'{i:02}') else os.makedirs(f'{i:02}')
                          
                        0

                        Можно пойти дальше и использовать EXIF метаданные для определения даты снимка. Время модификации файлов иногда не соответствуют времени снимка.

                          0
                          #!/bin/sh

                          for i in 'tv-shots0' 'tv-shots1' 'tv-shots2' 'tv-shots3'
                          do
                          echo $i

                          cd /tank/CAMERAS/$i

                          find. -name "*.png" -print |
                          ls -lUrD %Y-%m-%d_%H:%M:%S $line |
                          while read line
                          do
                          echo $line
                          namefile=`echo "$line" | awk '{ print $7 }'`
                          myvar=`echo "$line" | awk '{ print $6 }'`
                          yearfile=`echo | awk '{ print substr("'"${myvar}"'",1,4)}'`
                          mounthfile=`echo | awk '{ print substr("'"${myvar}"'",6,2)}'`
                          dayfile=`echo | awk '{ print substr("'"${myvar}"'",9,2)}'`
                          echo namefile $namefile
                          echo yearfile $yearfile
                          echo mounthfile $mounthfile
                          echo dayfile $dayfile
                          if [! -f /tank/CAMERAS/$i.arch/$yearfile/$mounthfile/$dayfile ]; then
                          mkdir -p /tank/CAMERAS/$i.arch/$yearfile/$mounthfile/$dayfile
                          fi
                          mv $namefile /tank/CAMERAS/$i.arch/$yearfile/$mounthfile/$dayfile/
                          done

                          done

                          Only users with full accounts can post comments. Log in, please.