본문 바로가기

코딩/업무자동화

[파이썬/업무자동화] 파일명 규칙 따라 폴더 자동 분류하기

반응형

 

   다른 사람의 불편함을 해결해주는 업무자동화 포스팅 2편. 먼저 이번 사연을 보자.

 

 

 

출처 : https://quasarzone.com/bbs/qf_sw/views/27119

 

 

   이번 사연은 파일명 폴더 분류에 관한 것이다. 2020년 5월에 올라온 글이긴 하지만 파이썬으로 가능한 부분이라서 포스팅을 작성해본다.

 

  질문자는 특정 단어들이 규칙성있게 되어 있는 파일들을 폴더에 분류하고 싶어 한다. 추가로 엑셀에도 파일명을 정리할 수 있는 기능을 요구하였지만 이전 포스팅에도 많이 했던 부분이니 생략하고 폴더를 자동 분류하는 프로그램을 작성해보는 것을 목적으로 한다.

 

  폴더내 파일명을 엑셀 내 정리하는 방법은 아래 포스팅을 참고하면 된다.

(참고링크 : 2021.06.16 - [코딩/업무자동화] - [파이썬/업무자동화] 여러 폴더 안에 있는 파일명 한번에 바꾸기 2편)

 

 

 

1. 문제 정의

 

 

  위 사연을 코드로 구현하기 위해 상황을 아래와 같이 정리해보았다.

 

 

1) 특정 폴더에 아래 규칙을 가진 파일명이 다수 존재한다. 아래는 위 사연을 재현하여 가상의 파일을 만들어본 것이다.

질문자는 실제 13 기가바이트 용량의 txt파일이 있다고 하니 굉장히 많은 파일이 있을 것으로 추정된다.

 

전체 분류할 파일

 

 

2) 프로그램을 실행시키면 위 파일명의 "재물손괴", "미수", "횡령" 이라는 단어를 활용해서 자동으로 아래와 같이 폴더가 생성되어야 한다.

 

폴더 자동 생성

 

 

3) 각각 폴더에 맞게 파일이 자동으로 분류된다.

 

"재물손괴" 폴더에 파일 자동 분류

 

 

 

2. 모듈  함수 설명

 

 

1) 모듈 Import

 

 

  os 모듈과 shutil 모듈을 활용한다. 2개 모듈은 이전 포스팅에서도 활용한 적이 있다. 간단히 설명하면 os 모듈은 파일명, 폴더명을 읽어오는 모듈, shutil 모듈은 파일을 다른 디렉토리로 이동시킬 때 사용하는 모듈이다.

 

import os #파일명, 폴더명 정보를 읽어오기 위한 모듈
import shutil #파일 이동을 위한 모듈

 

 

2) 함수 정의

 

 

  이번 프로그램의 함수는 크게 3파트이다.  설명은 간단히 아래와 같이 정리해보았다.

 

 

함수명 설명
fileList(path_before) -. 전체 파일이 있는 경로(path_before)를 읽어와서 파일명을 읽어옴.
-. 파일명에서 "재물손괴", "횡령", "미수" 문자열을 리스트로 반환시킴
   (중복없이 반환)
makeFolder(path_after, file_list) -. 이동시킬 경로(path_after)에 fileLIst 함수에서 리턴 된 문자열 file_list
("재물손괴","횡령","미수")에 대한 폴더를 자동으로 생성.
moveFile(path_before, path_after) -. 이동 전 경로(path_before), 이동 경로(path_after)를 매개변수로 입력받아 파일을 실제 이동시키는 함수
-. 단, makeFolder가 먼저 실행되어 분류별 폴더가 생성되어있어야 정상적으로 동작함.

 

 

 

3. 함수 작성

 

 

1) def fileList(path_before):

 

 

  위 설명과 같이 파일명에서 분류("재물손괴","횡령","미수") 문자열을 중복없이 받아오는 함수이다.

 

 

<코드>

#파일명을 읽어와서 파일명의 분류 부분을 중복없이 리스트화
def fileList(path_before : str)->list :
    file_list = os.listdir(path_before) #폴더의 파일명을 리스트화
    category = [] #분류 데이터 저장을 위해 빈 리스트 생성
    for file in file_list:
        temp_list = file.split("_") #파일명중 "_"로 분리하여 리스트화
        category.append(temp_list[-2]) #리스트의 -2 인덱싱 데이터를 category에 추가

    temp_set = set(category) #중복을 제거하기 위해 set 사용
    result = list(temp_set) #중복 제거 후 다시 리스트화
    return result #결과 리턴

 

 

  코드에 대한 설명은 주석을 참고하면 되며, 위 코드에서 중요한 부분은 split 함수와 리스트 중복제거이다. split 함수는 특정 문자를 기준으로 문자열을 분리하고 리스트화시키는 부분이다. 이전에도 문자열 분리와 관련하여 포스팅 한 내용이 있으니 참고링크를 기재함.

(참고링크 : 2021.06.13 - [코딩/업무자동화] - [파이썬/업무자동화] 특정 문자 기준으로 문자열 분리 및 나열)

 

 

  위 temp_list를 출력하면 아래와 같다. 파일명(문자열)을 "_" 문자 기준으로 분리시켜 리스트화 시킨 결과이다. 따라서, temp_list[-2]라는 코드는 아래 문자열 리스트 중 -2번째 요소에 인덱싱한다는 의미이다. temp_list[4] 와 동일하다. 자세한 내용은 파이썬의 리스트 인덱싱에 대한 정보를 검색해보면 된다.

 

문자열 split 함수 사용 결과

 

  결과적으로 fileList 함수의 리턴값인 result를 출력해보면 아래와 같이 리스트 3개 요소를 확인할 수 있다.

 

 

<결과>

['재물손괴', '미수', '횡령']

 

 

 

2) def makeFolder(path_after, file_list):

 

 

   fileList 함수의 결과 리턴값인 file_list와 이동시킬 경로인 path_after를 매개변수로 입력받아 분류할 폴더를 자동으로 생성한다.

 

 

<코드>

# 분류 리스트를 받아와서 정해진 위치에 폴더 생성
def makeFolder(path_after : str, file_list : list):    
    #폴더가 이미 생성되어있다면 오류가 발생하므로 예외처리 진행
    for file in file_list:
        try:
            os.makedirs(path_after+"/"+file)
        except:
            pass

 

 

  예외처리 구문인 try, except를 사용한 이유는 폴더가 이미 생성되어있는 경우 오류가 발생하기 때문에 사용했다. 해당 함수를 실행시키면 아래와 같이 분류에 대한 폴더가 자동 생성 된다.

 

 

 

 

 

 

3) def moveFile(path_before, path_after):

 

 

  마지막 함수인 moveFile은 전체 파일이 있는 경로, 이동시킬 경로를 받아와 파일을 직접 이동시키는 함수이다. 이 함수의 주의점은 이미 makeFolder 함수를 통해 각 폴더가 생성되어있어야 정상적으로 작동하는 것이다.

 

 

<코드>

#파일을 폴더 분류에 맞게 이동
def moveFile(path_before, path_after):
    folderlist = os.listdir(path_after) #이동시킬 경로에 생성된 분류별 폴더 리스트화
    filelist = os.listdir(path_before) #이동시킬 파일명들을 리스트화
    dict = {} #빈 딕셔너리 생성

    #파일명에 대한 폴더명을 딕셔너리로 저장
    for file in filelist:
        temp_list = file.split("_") 
        dict[file]=temp_list[-2] # {'파일명' : '분류'} 형태의 딕셔너리 생성
    
    #딕셔너리 정보 활용하여 파일 이동
    for key, value in dict.items():
        shutil.move(path_before+"/"+key, path_after+"/"+value)

 

 

  해당 함수의 컨셉은 딕셔너리를 활용했다. 딕셔너리 {Key : Value} 형태에서 Key는 파일명, Value는 분류명으로 생성하여 파일을 분류하는 것이다. 위 코드 중 dict를 출력해보면 아래와 같은 결과를 확인할 수 있다.

 

 

딕셔너리 dict 출력 결과

 

 

  위 딕셔너리를 for문을 통해 각각 요소에 인덱싱하고 shutil 모듈의 move 함수를 통해 각 분류에 맞게 이동시킨다. dict.items( )는 딕셔너리의 각 요소에 접근할수 있는 반복 자료형이다.

 

#딕셔너리 정보 활용하여 파일 이동
for key, value in dict.items():
    shutil.move(path_before+"/"+key, path_after+"/"+value)

 


** 딕셔너리 관련 포스팅

2021.06.13 - [코딩/Python] - [Python/파이썬] 자료형 - Dictionary 1편 : 기초

2021.06.19 - [코딩/Python] - [Python/파이썬] 자료형 - Dictionary 2편 : 딕셔너리 컴프리헨션


 

  shutil의 move함수 사용법은 아래와 같다.

 

shutil.move("이동시킬 파일들이 있는 경로", "이동할 파일 경로")

 

 

 

4) 실행 코드 및 결과

 

<코드>

if __name__ == "__main__" :
    #분류할 파일이 있는 위치 폴더
    path_before = r"분류필요한 파일 경로"
    file_list = fileList(path_before)

    #옮길 경로 폴더
    path_after = r"옮길 폴더 경로"
    makeFolder(path_after, file_list)
    moveFile(path_before, path_after)

 

 

<실행 결과>

<파일 자동 분류 실행 결과>

 

 

 

4. 전체 코드 및 파일

 

 

<전체 코드>

#folder_move
import os #파일명, 폴더명 정보를 읽어오기 위한 모듈
import shutil #파일 이동을 위한 모듈

#파일명을 읽어와서 파일명의 분류 부분을 중복없이 리스트화
def fileList(path_before : str)->list :
    file_list = os.listdir(path_before) #폴더의 파일명을 리스트화
    category = [] #분류 데이터 저장을 위해 빈 리스트 생성
    for file in file_list:
        temp_list = file.split("_") #파일명중 "_"로 분리하여 리스트화
        category.append(temp_list[-2]) #리스트의 -2 인덱싱 데이터를 category에 추가

    temp_set = set(category) #중복을 제거하기 위해 set 사용
    result = list(temp_set) #중복 제거 후 다시 리스트화
    print(result)
    return result #결과 리턴


#죄 분류 리스트를 받아와서 정해진 위치에 폴더 생성
def makeFolder(path_after : str, file_list : list):    
    #폴더가 이미 생성되어있다면 오류가 발생하므로 예외처리 진행
    for file in file_list:
        try:
            os.makedirs(path_after+"/"+file)
        except:
            pass

#파일을 폴더 분류에 맞게 이동
def moveFile(path_before, path_after):
    folderlist = os.listdir(path_after)
    filelist = os.listdir(path_before)
    dict = {}

    #파일명에 대한 폴더명을 딕셔너리로 저장
    for file in filelist:
        temp_list = file.split("_")
        dict[file]=temp_list[-2]
     
    print(dict)
    
    #딕셔너리 정보 활용하여 파일 이동
    for key, value in dict.items():
        shutil.move(path_before+"/"+key, path_after+"/"+value)
    
    
if __name__ == "__main__" :
    #분류할 파일이 있는 위치 폴더
    path_before = r"분류필요한 파일 경로"
    file_list = fileList(path_before)

    #옮길 경로 폴더
    path_after = r"결과폴더경로"
    makeFolder(path_after, file_list)
    moveFile(path_before, path_after)

 

.py 파일은 아래 첨부파일을 다운받으면 된다.

 

filemove.zip
0.00MB

 

728x90