본문 바로가기
코딩/파이썬

디렉토리 관리 프로그램

by Song1234 2024. 3. 22.

1. 압축파일 정리하기

import os
import glob
import zipfile
import shutil
import fnmatch
import pathlib
# 현재 경로 알아보기
os.getcwd()
'C:\\****\\***\\Python\\jupyter\\filemanager'
# 정리 대상 디렉토리 경로 설정하기
target_path = './정리'
# '정리' 디렉토리에서 압축 파일 확인하기
# for filename in glob.glob('**/*.zip'):
#     print(filename)
zipfile_path = []
for filename in glob.glob(os.path.join(target_path,'**/*.zip'), recursive=True):
    zipfile_path.append(filename)
    print(zipfile_path)
['./정리\\데이터저장_물류.zip']
# 압축 파일 해제하기
# for filename in zipfile_path:
#     with zipfile.ZipFile('./정리\\데이터저장_물류.zip') as myzip:
#         myzip.extractall('./정리/압축푸는곳') # 인코딩 되어있는 상태로 압축이 해제되어 파일을 읽을수가 없다

for filename in zipfile_path:
    with zipfile.ZipFile('./정리\\데이터저장_물류.zip') as myzip:
        zipinfo = myzip.infolist()
        # print(zipinfo) # 압축파일 정보
        for info in zipinfo:
            decode_name = info.filename.encode('cp437').decode('euc-kr') # cp437로 인코딩 된 파일을 euc-kr 형태로 디코딩
            info.filename = os.path.join(target_path, decode_name)
            myzip.extract(info)

인코딩상태

 

디코딩 상태

 

2. 파일명 정리하기

!pip install openpyxl # openptxl 엑셀 파일 에 대한 모듈은 기본으로 깔려있지 않기때문에 직접 설치를 해준다
Collecting openpyxl
  Downloading openpyxl-3.1.2-py2.py3-none-any.whl (249 kB)
     ---------------------------------------- 0.0/250.0 kB ? eta -:--:--
     ------------------------------------- 250.0/250.0 kB 15.0 MB/s eta 0:00:00
Collecting et-xmlfile
  Downloading et_xmlfile-1.1.0-py3-none-any.whl (4.7 kB)
Installing collected packages: et-xmlfile, openpyxl
Successfully installed et-xmlfile-1.1.0 openpyxl-3.1.2



[notice] A new release of pip is available: 23.0.1 -> 24.0
[notice] To update, run: python.exe -m pip install --upgrade pip
import openpyxl as opx
def getFileName(target_path):
    wb = opx.Workbook()
    ws = wb.active # 엑셀 사용

    ws.cell(row=1, column=1).value = '파일경로' # row(열) column(행) 에 값을 입력한다
    ws.cell(row=1, column=2).value = '파일명(변경전)'
    ws.cell(row=1, column=3).value = '파일명(변경후)'

    i = 2

    current_dir = target_path
    filelist = os.listdir(current_dir)

    for filename in filelist:
        ws.cell(row=i, column=1).value = current_dir + '/'
        ws.cell(row=i, column=2).value = filename
        i = i + 1

    wb.save(os.path.join(target_path, 'filelist.xlsx'))
   # 디렉토리 리스트를 뽑아 엑셀의 행렬에 맞춰 값을 입력해준다

생성된 엑셀파일

 

getFileName(target_path)

3. 파일명 변경하기

wb = opx.load_workbook(os.path.join(target_path, 'filelist.xlsx'))
ws = wb.active

 

dirpath = [r[0].value for r in ws]
file_before = [r[1].value for r in ws]
print(dirpath)
['파일경로', './정리/', './정리/', './정리/', './정리/', './정리/', './정리/', './정리/', './정리/', './정리/', './정리/', './정리/', './정리/', './정리/', './정리/', './정리/', './정리/', './정리/', './정리/', './정리/', './정리/', './정리/', './정리/', './정리/', './정리/', './정리/', './정리/', './정리/', './정리/', './정리/', './정리/', './정리/', './정리/', './정리/']
# exceLread() 함수를 만들어 아래와 같이 값을 반환하는 함수를 만들어보자
# 튜플으로 (디렉토리, 변경전파일, 변경후파일) 나열되는 리스트를 반환
# 예) [('./정리/', 'A_2022_01_13_부서로그_인사_001.pdf','A_2022_01_13_부서로그_인사_001.pdf')
# './정리/', 'A_2022_01_13_부서로그_인사_002.pdf', 'A_2022_01_13_부서로그_인사_002.pdf')]
def exceLread(filepath):
    wb = opx.load_workbook(filepath)
    ws = wb.active

    dirpath = [r[0].value for r in ws] # 엑셀에 디렉토리 주소를 불러와 저장해준다
    file_before = [r[1].value for r in ws] # 엑셀에 파일 정리전 열의 내용들을 불러온다
    file_after = [r[2].value for r in ws] # 파일정리 후 내용들을 불러온다

    datalist = []
    # for i in zip(dirpath, file_before, file_after):
    #     datalist.append(i)
    len_num = len(dirpath)
    for i in range(1, len_num):
        temp_tuple =  (dirpath[i], file_before[i], file_after[i])
        datalist.append(temp_tuple)
    return datalist
    # 주소 와 내용들을 하나씩 뽑아와 튜플로 묶어준뒤 리스트에 어팬드 시켜준다
rename_list = exceLread(os.path.join(target_path, 'filelist.xlsx'))
print(rename_list)
[('./정리/', 'A_2022_01_13_부서로그_인사_001.pdf', 'A_2022_01_13_부서로그_인사_001.pdf'), ('./정리/', 'A_2022_01_13_부서로그_인사_002.pdf', 'A_2022_01_13_부서로그_인사_002.pdf'), ('./정리/', 'A_2022_01_13_부서로그_인사_003.pdf', 'A_2022_01_13_부서로그_인사_003.pdf'), ('./정리/', 'A_2022_04_10_생산로그_생산_001.pdf', 'A_2022_04_10_생산로그_생산_001.pdf'), ('./정리/', 'A_2022_04_10_생산로그_생산_002.pdf', 'A_2022_04_10_생산로그_생산_002.pdf'), ('./정리/', 'A_2022_04_10_생산로그_생산_003.pdf', 'A_2022_04_10_생산로그_생산_003.pdf'), ('./정리/', 'A_2022_04_10_생산로그_생산_004.pdf', 'A_2022_04_10_생산로그_생산_004.pdf'), ('./정리/', 'A_2022_06_30_생산로그_생산_001.pdf', 'A_2022_06_30_생산로그_생산_001.pdf'), ('./정리/', 'A_2022_06_30_생산로그_생산_002.pdf', 'A_2022_06_30_생산로그_생산_002.pdf'), ('./정리/', 'A_2022_07_20_부서로그_인사_001.pdf', 'A_2022_07_20_부서로그_인사_001.pdf'), ('./정리/', 'A_2022_07_20_부서로그_인사_002.pdf', 'A_2022_07_20_부서로그_인사_002.pdf'), ('./정리/', 'A_2022_07_20_부서로그_인사_003.pdf', 'A_2022_07_20_부서로그_인사_003.pdf'), ('./정리/', 'A_2022_07_20_부서로그_인사_004 (1).pdf', 'A_2022_07_20_부서로그_인사_004.pdf'), ('./정리/', 'B_2022_02_20_상반기_클래스설계_001.xlsx', 'B_2022_02_20_상반기_클래스설계_001.xlsx'), ('./정리/', 'B_2022_02_20_상반기_클래스설계_002.xlsx', 'B_2022_02_20_상반기_클래스설계_002.xlsx'), ('./정리/', 'B_2022_06_20_하반기_클래스설계_001.xlsx', 'B_2022_06_20_하반기_클래스설계_001.xlsx'), ('./정리/', 'B_2022_06_30_하반기_클래스설계_002.xlsx', 'B_2022_06_30_하반기_클래스설계_002.xlsx'), ('./정리/', 'C_2022_03_30_데이터베이스_ERD_001.xlsx', 'C_2022_03_30_데이터베이스_ERD_001.xlsx'), ('./정리/', 'C_2022_03_30_데이터베이스_ERD_002.xlsx', 'C_2022_03_30_데이터베이스_ERD_002.xlsx'), ('./정리/', 'C_2022_03_30_데이터베이스_ERD_003.xlsx', 'C_2022_03_30_데이터베이스_ERD_003.xlsx'), ('./정리/', 'C_2022_09_10_데이터베이스_ERD_001 (1).xlsx', 'C_2022_09_10_데이터베이스_ERD_001.xlsx'), ('./정리/', 'C_2022_09_10_데이터베이스_ERD_002.xlsx', 'C_2022_09_10_데이터베이스_ERD_002.xlsx'), ('./정리/', 'C_2022_09_10_데이터베이스_ERD_003.xlsx', 'C_2022_09_10_데이터베이스_ERD_003.xlsx'), ('./정리/', 'D_20220110_데이터저장_물류_001.pdf', 'D_20220110_데이터저장_물류_001.pdf'), ('./정리/', 'D_20220110_데이터저장_물류_002.pdf', 'D_20220110_데이터저장_물류_002.pdf'), ('./정리/', 'D_20220723_데이터저장_물류_001.pdf', 'D_20220723_데이터저장_물류_001.pdf'), ('./정리/', 'D_20220723_센터가동현황_물류_002.pdf', 'D_20220723_센터가동현황_물류_002.pdf'), ('./정리/', '내사진.jpg', '내사진.jpg'), ('./정리/', '데이터저장_물류.zip', '데이터저장_물류.zip'), ('./정리/', '새파일1_복사본.txt', '새파일.txt'), ('./정리/', '압축푸는곳', '압축푸는곳'), ('./정리/', '점심시간.txt', '점심시간.txt'), ('./정리/', '주피터노트북.txt', '주피터노트북.txt')]
def fileRename(datalist):
    for data in datalist:
        print(data[1] + '의 파일명을 ' + data[2] + '로 변경합니다.')
        shutil.move(data[0]+data[1], data[0]+data[2])
        
        # sutil으로 파일을 잘라내고 이름을 변경후 다시 같은 자리에 붙여 넣는식으로 이름을 변경해준다
fileRename(rename_list)
A_2022_01_13_부서로그_인사_001.pdf의 파일명을 A_2022_01_13_부서로그_인사_001.pdf로 변경합니다.
A_2022_01_13_부서로그_인사_002.pdf의 파일명을 A_2022_01_13_부서로그_인사_002.pdf로 변경합니다.
A_2022_01_13_부서로그_인사_003.pdf의 파일명을 A_2022_01_13_부서로그_인사_003.pdf로 변경합니다.
A_2022_04_10_생산로그_생산_001.pdf의 파일명을 A_2022_04_10_생산로그_생산_001.pdf로 변경합니다.
A_2022_04_10_생산로그_생산_002.pdf의 파일명을 A_2022_04_10_생산로그_생산_002.pdf로 변경합니다.
A_2022_04_10_생산로그_생산_003.pdf의 파일명을 A_2022_04_10_생산로그_생산_003.pdf로 변경합니다.
A_2022_04_10_생산로그_생산_004.pdf의 파일명을 A_2022_04_10_생산로그_생산_004.pdf로 변경합니다.
A_2022_06_30_생산로그_생산_001.pdf의 파일명을 A_2022_06_30_생산로그_생산_001.pdf로 변경합니다.
A_2022_06_30_생산로그_생산_002.pdf의 파일명을 A_2022_06_30_생산로그_생산_002.pdf로 변경합니다.
A_2022_07_20_부서로그_인사_001.pdf의 파일명을 A_2022_07_20_부서로그_인사_001.pdf로 변경합니다.
A_2022_07_20_부서로그_인사_002.pdf의 파일명을 A_2022_07_20_부서로그_인사_002.pdf로 변경합니다.
A_2022_07_20_부서로그_인사_003.pdf의 파일명을 A_2022_07_20_부서로그_인사_003.pdf로 변경합니다.
A_2022_07_20_부서로그_인사_004 (1).pdf의 파일명을 A_2022_07_20_부서로그_인사_004.pdf로 변경합니다.
B_2022_02_20_상반기_클래스설계_001.xlsx의 파일명을 B_2022_02_20_상반기_클래스설계_001.xlsx로 변경합니다.
B_2022_02_20_상반기_클래스설계_002.xlsx의 파일명을 B_2022_02_20_상반기_클래스설계_002.xlsx로 변경합니다.
B_2022_06_20_하반기_클래스설계_001.xlsx의 파일명을 B_2022_06_20_하반기_클래스설계_001.xlsx로 변경합니다.
B_2022_06_30_하반기_클래스설계_002.xlsx의 파일명을 B_2022_06_30_하반기_클래스설계_002.xlsx로 변경합니다.
C_2022_03_30_데이터베이스_ERD_001.xlsx의 파일명을 C_2022_03_30_데이터베이스_ERD_001.xlsx로 변경합니다.
C_2022_03_30_데이터베이스_ERD_002.xlsx의 파일명을 C_2022_03_30_데이터베이스_ERD_002.xlsx로 변경합니다.
C_2022_03_30_데이터베이스_ERD_003.xlsx의 파일명을 C_2022_03_30_데이터베이스_ERD_003.xlsx로 변경합니다.
C_2022_09_10_데이터베이스_ERD_001 (1).xlsx의 파일명을 C_2022_09_10_데이터베이스_ERD_001.xlsx로 변경합니다.
C_2022_09_10_데이터베이스_ERD_002.xlsx의 파일명을 C_2022_09_10_데이터베이스_ERD_002.xlsx로 변경합니다.
C_2022_09_10_데이터베이스_ERD_003.xlsx의 파일명을 C_2022_09_10_데이터베이스_ERD_003.xlsx로 변경합니다.
D_20220110_데이터저장_물류_001.pdf의 파일명을 D_20220110_데이터저장_물류_001.pdf로 변경합니다.
D_20220110_데이터저장_물류_002.pdf의 파일명을 D_20220110_데이터저장_물류_002.pdf로 변경합니다.
D_20220723_데이터저장_물류_001.pdf의 파일명을 D_20220723_데이터저장_물류_001.pdf로 변경합니다.
D_20220723_센터가동현황_물류_002.pdf의 파일명을 D_20220723_센터가동현황_물류_002.pdf로 변경합니다.
내사진.jpg의 파일명을 내사진.jpg로 변경합니다.
데이터저장_물류.zip의 파일명을 데이터저장_물류.zip로 변경합니다.
새파일1_복사본.txt의 파일명을 새파일.txt로 변경합니다.
압축푸는곳의 파일명을 압축푸는곳로 변경합니다.
점심시간.txt의 파일명을 점심시간.txt로 변경합니다.
주피터노트북.txt의 파일명을 주피터노트북.txt로 변경합니다.
# 디렉토리안의 파일을 확인하여 카테고리를 뽑아주는 함수를 만들어보자
# ['생산', '클래스설계', '물류', 'ERD', '인사']
# fnmatch.fnmatch() 메서드를 사용
def categoryList(target_path):
    file_list = []
    for filename in os.listdir(target_path): # 디렉토리 내의 파일들을 불러온뒤 하나씩 담아서 비교
        if fnmatch.fnmatch(filename, '*_[0-9][0-9][0-9].*'): # 파일 이름에 공통된 패턴을 찾는다
            file_list.append(filename)
    category = []
    for file in file_list:
        temp_list = file.split('_') # split 을 통해 파일명의 언더바 기준으로 잘라서 리스트에 저장)
        category.append(temp_list[-2]) # 저장후 카테고리명이 적혀있는 끝에서 두번째 값을 저장해준다
    category = set(category) # 세트로 묶어 중복을 없애준다
    return list(category) # 리스트로 저장을 하기위해 변환
categoryList(target_path)
['클래스설계', '인사', '물류', '생산', 'ERD']
categorylist = categoryList(target_path) + ['기타'] # 리스트에 기타 카테고리 추가
print(categorylist)
['클래스설계', '인사', '물류', '생산', 'ERD', '기타']
def makeDir(new_path, categorylist):
    for category in categorylist:
        new_dir = pathlib.Path(os.path.join(new_path,category))
        # './new_정리' + '/클래스설계', '/물류', '/생산'..
        # parents: 상위 디렉토리가 없을 경우 상위 디렉토리도 생성
        # exist_ok: 디렉토리가 이미 존재하는 경우 오류를 발생시키지 않도록 함
        new_dir.mkdir(parents=True, exist_ok=True)

 

파일정리를 위한 카테고리 폴더 생성

new_path = './new_정리'
target_path = './정리'

 

makeDir(new_path, categorylist)
def moveFile(target_path, categorylist, new_path): # 파일을 옮기기 위한 함수 생성
    dirlist = os.listdir(new_path)
    # dirlist = 
    filelist = os.listdir(target_path)
    categorydic = {}
	# 기존 주소와 파일을 옮길 주소의 파일들의 이름을 저장해준다
    for file in filelist:
        try: 
            temp_list = file.split('_') # split으로 분류명 을 저장
            assert temp_list[-2] in categorylist
            categorydic[file] = temp_list[-2] # {'파일명':'분류명'} 형식으로 딕셔너리로 저장
        except:
            categorydic[file] = '기타' # {'파일명':'기타'} # 분류명이 없다면 기타 로 저장
    for key, value in categorydic.items():
        shutil.copy(target_path + '/' + key, new_path + '/' + value) # './정리/파일명'에서 './new_정리/분류명폴더' 로 이동시켜준다
moveFile(target_path, categorylist, new_path)

 

분류명 대로 저장이 잘 되었다

 

assert메서드

  • 주어진 조건이 True인지 확인하고 조건이 False이면 예외를 발생시키는데 사용
  • 주로 디버깅 및 테스트 목적으로 코드에서 사용
  • 디버그 모드에만 동작되며,배포시에는 작동되지 않음

'코딩 > 파이썬' 카테고리의 다른 글

파이썬 비동기  (2) 2024.06.07
데이터베이스와 MongoDB  (1) 2024.06.07
변수 타입 어노테이션  (1) 2024.03.21
파일 입출력을 이용한 단어장 만들기  (0) 2024.03.21
파이썬 파일입출력  (0) 2024.03.20