반응형

imageReDirectory.py
0.01MB

 

 

하위 폴더까지 조회해서 이동하는 거랑 실제 위치에서 실행 안되는 경우 파일을 찾을 수 없는 등의 오류가 있어 조금 변경해 보았다.

생각보다 속도도 빠른 편인듯.

 

참고로 pillow 패키지를 사용하는데 설치된 파이썬에 해당 패키지를 설치해야 하므로 아래와 같이 설치하고 진행한다.

python3 -m pip install pillow

 

 

Python 사진 자동 정리 프로그램 개발  - 참고 링크: https://hellojason.tistory.com/27

 

[Python] 사진 자동 정리 프로그램 개발 (EXIF)

핸드폰/디카로 사진 촬영하는 일은 이제 일상이 되었습니다. Google Photo 를 사용하면 간편하지만, 비용도 문제고 과거 파일도 업로드해야하고, 용량이 크면 비용도 문제가 됩니다. 저도 NAS에 아이

hellojason.tistory.com

 

개선 내용

 

1. 하위 폴더 조회해서 이동할 건지 설정 : subfolder = False > True

2. 중복된 파일의 접두사 : duplicatePrefix = 'dup_'

3. 실행 위치에 따른 선택:

    cur_dir = os.getcwd()  # python 을 실행한 위치

    cur_dir = ‘’ # 다른 곳에서 실행하지만 사진을 조회하고 실행하려는 위치

 

import os
import shutil

from PIL import Image
from PIL.ExifTags import TAGS
from datetime import datetime

# 디버그 모드 활성화 여부 - True, False
DEBUG = True

# 하위 폴더까지 확인하기
subfolder = False

# 이동하려는 곳의 파일이 존재한다면 추가하려는 앞자리
duplicatePrefix = 'dup_'

# 이미지 확장자
img_ext = ['.jpg', '.jpeg', '.JPG', '.JPEG', '.png', '.PNG', '.bmp', '.BMP']
# 영상 확장자
mov_ext = ['.mp4', '.MP4', '.avi', '.AVI', 'mts', '.MTS', '.m2ts', '.M2TS']

# 이미지 파일 저장 리스트
img_list = []
# 영상 파일 저장 리스트
mov_list = []
# 기타 파일 저장 리스트
etc_list = []

# 실행 현재 위치 - 하위 폴더 조회해서 모두 이동시켜 버림
# cur_dir = os.getcwd();

# 실행 위치(파일 검색하는 위치) 고정
cur_dir = '/Users/jymun/Desktop/Photo/PY_TestImage/'

# 디버그 모드 시작하기
if DEBUG :
    print('img_list length : ', len(img_list))
    print(f'current_dir : {cur_dir}')

# 이미지 날짜 정보 조회하기 - 함수
def getImageDate(image, DEBUG=False):
    '''
    이미지 EXIF 정보 읽기 - 이미지 생성 년, 월 리턴
    '''
    img = Image.open(image)
    img_date = []

    if DEBUG : print(img.filename)
    
    # EXIF 정보로 이미지 촬영일 체크
    img_info = img._getexif()
    if img_info is not None:
        for tag_id in img_info:
            tag = TAGS.get(tag_id, tag_id)
            data = img_info.get(tag_id)

            if tag == 'DateTime' or tag == 'DateTimeOriginal':      # 촬영일 존재하면 년,월 세팅
                data = data.replace('-',':')                        # '-' 일자 구분자를 :로 변환

                # meta정보 고려해서 10자리 끊고 -> 빈칸 0 trim후 0 채워넣기
                data = data[:11]                                    # yyyy:mm:dd 10자리만 읽기
                data = data.replace(' ','0')                        # 공백 '0' 채움
                date = data.split(':')                              # date = [년, 월, 일]
                if DEBUG: print(f'Data : {data}, Date : {date}')
                try:
                    img_date.append(date[0])
                    img_date.append(date[1])
                except:
                    print('!!!!!! ERRROR !!!!!!!!!')
                    print(f'img name : ', image)
                    print(f'data : {data}')
                    print(f'date : {date}')
                    img_date[0] = 'error'           # 강제 error 세팅
                    img_date.append('00')           # 두번째 값 '00' 추가
                    print(f'img_date : {img_date}')

            if DEBUG:
                print(f'>>>>> {tag:25}: {data}')
            
    # EXIF 값이 없으면, 파일 생성일 세팅
    if len(img_date) == 0 :
        date = datetime.fromtimestamp(os.path.getctime(image)).strftime('%Y:%m:%d').split(':')
        img_date.append(date[0])
        img_date.append(date[1])
            
    if(DEBUG):
        print(f'date : {date}')
        print(f'img_date : {img_date}')
                
    return img_date

# 이미지 파일 이동 관련
def moveImageFiles(img_list, DEBUG=False):
    count = 0
    img_cnt = len(img_list)
    print(f'Target file count : {img_cnt}')
    for img in img_list:
        img_date = getImageDate(img, DEBUG)
        if DEBUG : print(img_date[0], img_date[1], img)

        # 파일 위치 구분함
        imgPath = img.split('/')
        # 마지막 파일명을 반환
        imgName = imgPath.pop();
        # 파일명 앞 위치를 저장
        imgOrgPath = ('/').join(imgPath);

        if DEBUG : print(f'name= {imgName}, {imgOrgPath}')

        # 새로운 폴더 위치 - 년도 / 월
        dir_path = os.path.join(img_date[0], img_date[1])
        # 원래 파일 위치
        s_path = os.path.join(img)
        # 이동하려는 폴더 위치 - 시작 위치를 기본으로 함
        t_imgPath = os.path.join(cur_dir, dir_path);
        # 이동하려는 폴더와 파일 위치
        t_path = os.path.join(t_imgPath, imgName)

        if DEBUG:
            print(f'dir_path : {dir_path}')
            print(f'Source_path : {s_path}')
            print(f'Target_path : {t_path}')

        # 년도/월 폴더가 있는지 확인 - 없으면 생성
        if not os.path.exists(t_imgPath):
            os.makedirs(t_imgPath)

        # 년도/월 폴더와 파일이 재하는 경우 - (prefix : dup_ 추가)
        if os.path.isfile(t_path) :
            dup_name = duplicatePrefix + imgName
            t_path = os.path.join(t_imgPath, dup_name)

        # 파일 이동
        shutil.move(s_path, t_path)

        print(f'{img} ====> {t_path}')
        count = count+1

    print(f'{count} files moved!')

# 현재 폴더(하위까지 조회하기)
if subfolder:
    for (root, directories, files) in os.walk(cur_dir):
        for file in files:
            file_path = os.path.join(root, file)
            print(f' > file(s) Name: {file_path}')
            
            if os.path.isfile(file_path):
                name,ext = os.path.splitext(file)
                if ext in img_ext:
                    img_list.append(file_path)
                elif ext in mov_ext:
                    mov_list.append(file_path)
                else:
                    etc_list.append(file_path)
            else:
                print(f'[{file_path}] is not File')
else:
    # 현재 폴더만 조회하기
    for file in os.listdir(cur_dir):
        file_path = os.path.join(cur_dir, file)
        if os.path.isfile(file_path):
            name,ext = os.path.splitext(file)
            if ext in img_ext:
                img_list.append(file_path)
            elif ext in mov_ext:
                mov_list.append(file_path)
            else:
                etc_list.append(file_path)
        else:
            print(f'[{file_path}] is not File')

# 결과 조회       
print('====== 최종 결과 ======');
print(f'Working Directory : {cur_dir}');
print(f'{len(img_list)} file(s) detected.')

# 최종 결과 확인
'''
if DEBUG:
    print(f'img_list: {img_list}')
    print(f'mov_list: {mov_list}')
    print(f'etc_list: {etc_list}')
'''
# 실행
moveImageFiles(img_list, DEBUG)

 

반응형
반응형

 

VSCODE 명령 팔레트 열기 : Command + Shift + P

 

1. Python: 인터프리터 선택

 

2. 프로젝트 폴더 선택

 

3. 인터프리터 경로 설정: 최근에 설치한 폴더가 맞는지 확인 아니라면 경로 입력으로 진행

 

반응형
반응형

Mac(Sonoma 14.2.1 기준 작성, 2024.02.03.)에서 Python 업데이트 방법에 대해 기록해 본다.

 

먼저 설치된 버전을 확인하는 과정부터 설명하자면

# 버전확인
python3 -V

# 버전확인2
python -V

# 설치된 위치 확인
which python3
결과 > python3: aliased to /usr/local/bin/python3

 

기존에 어떤 걸로 설정되어 있는지 모르겠지만, 필자의 경우는 python3 -V로 했을 때 나왔다.

최신 버전을 다운로드 하고자 한다면 아래 파이썬 홈페이지를 통해서 다운로드 받아 진행한다.

 

1. 파이썬 홈페이지에서 다운로드 - https://www.python.org/

 

Welcome to Python.org

The official home of the Python Programming Language

www.python.org

 

 

2. 다운로드한 걸 설치( 2024.02.03. 기준 3.12.1 버전이 최신)한다.

  아래의 위치로 설치가 되는 것을 확인했다.

설치위치: /usr/local/bin/python3.12

 

3. alias를 변경

alias python=/usr/local/bin/python3.12
alias python3=/usr/local/bin/python3.12

# python, python3 로 호출할 수 있도록 설정

python -V
결과 > Python 3.12.1

python3 -V
결과 > Python 3.12.1

 

반응형

+ Recent posts