[파이썬/RPA] 파일명 규칙 따라 파일 분류하기

seulzzang·2022년 9월 13일
0

파이썬/RPA

목록 보기
1/6

오늘부터 RPA 수업을 진행한다.
학부생 시절 4학년 1학기에 인공지능 수업을 들었을 때 파일 읽고 쓰고 불러오는 걸 했던 기억이 잠깐 나는데 그때 당시 프로젝트 진행할때 우리가 받은 데이터 파일명에 규칙이 없어서 분류하기가 힘들었다🤔
아무튼 오늘 수업에서 다룬 실습내용을 정리하고자 한다!

📍파일 자동화

  • 파이썬에는 파일 관리를 위한 라이브러리를 가지고 있다.
    - os: 운영체제와 관련된 라이브러리
    - shutil: 파일, 폴더와 관련된 라이브러리
  • 파이썬 모든 버전에서 지원하는 라이브러리이기 때문에 별도 설치가 필요하지 않다.

📑os 함수

  • os.listdir('폴더경로') : 하위 파일, 폴더 리스트 확인
  • os.path.exists('경로'), os.path.isdir('경로') : 경로 존재 여부 확인 (Boolean값을 가짐.)
  • os.makedirs('경로') : 경로에 맞는 폴더 생성
  • os.remove('경로') : 해당 경로에 있는 파일을 제거

📑shutil 함수

  • shutil.copyfile('파일경로', '복사할 파일 경로') : 파일복사
  • shutil.rmtree('경로') : 경로 하위 디렉토리와 파일 삭제

📍실습 1

  • 파일명이 날짜와 시간으로 구성된 파일을 날짜별로 폴더를 만들어서 자동 분류하는 프로그램을 개발해주세요. 파일들은 미리 만들어 둔 sample을 활용해주세요. 파일명은 TEST_연-월-일_시-분-초.pdf로 만들어져 있습니다.

📖 풀이


경로는 위와 같다.

pdf_files에는 이런식으로 TEST_연-월-일_시-분-초.pdf 파일 1000개가 존재한다.
파일 명이 TEST_연-월-일_시-분-초.pdf로 이루어져 있기 때문에

file_list[0].split('_')
<출력>
['TEST', '2019-1-10', '12-21-3.pdf']

.split('_')으로 파일명을 분리할 수 있다. 1번 인덱스가 날짜부분이므로 pdf_date에 그 부분만 따로 저장해서 받아준다.
os.isdir()을 이용하여 폴더가 없으면 (반환 값이 False이면) os.makedirs()를 이용해 폴더를 생성해주는 방식.

💻나의 코드

import os
import shutil
PDF_DIR = './실습1/pdf_files/'
file_list = os.listdir(PDF_DIR)
pdf_date = []
for file in file_list:
    # '_' 기준으로 이름 나누기
    temp_list = file.split('_')
    # pdf_date에 날짜만 저장
    pdf_date.append(temp_list[1])
    # 폴더 생성
    for i in range(len(pdf_date)):
        # 폴더가 없으면(.isdir이 False이면)
        if os.path.isdir(PDF_DIR + pdf_date[i]) == False:
            os.makedirs(PDF_DIR + pdf_date[i])
    # 파일 복사해주기
    shutil.copyfile(PDF_DIR + file, PDF_DIR + pdf_date[i] + '/' + file)

코드를 실행하면

이런식으로 폴더가 잘 생성되고 파일도 잘 복사된 것을 확인할 수 있다.
폴더생성시 이미 폴더가 존재하는 경우 에러가 뜨는데

    if os.path.isdir(PDF_DIR + folder_name):
        pass
    # 존재하지 않으면
    else:
        os.makedirs(PDF_DIR + folder_name)
            #폴더 생성

이렇게 if문을 사용해주거나

    try:
        os.makedirs()
    except:
        pass

예외처리를 해주면 된다.
다만 내 코드는 이중for문이라서 소요시간이 좀 오래걸림..

이런거 할 때 마다 느끼는데.. 정말 기초가 너무너무너무 중요한 것 같다.

💻 강사님 코드

import os
import shutil
PDF_DIR = './pdf_files/'
file_list = os.listdir(PDF_DIR)
for file in file_list:
    folder_name = file.split('_')[1]
    if os.path.isdir(PDF_DIR + folder_name):
        pass
    else:
        os.makedirs(PDF_DIR + folder_name)
    original_dir = PDF_DIR + file
    # ./pdf_files/TEST_2019-1-10_12-21-3.pdf
    target_dir = PDF_DIR + folder_name + '/' + file
    # ./pdf_files/2019-01-10/TEST_2019-1-10_12-21-3.pdf
    shutil.move(original_dir, target_dir)

이중for문을 굳이 사용할 필요가 없음.
정규식도 이용할 수 있다고 하셨다. 아래와 같이..

import re
re.search('(?<=\_)[^_]*(?=\_)', file.group())

근데 사실 이거보단 .split()써주는게 훨씬 쉽고 간단한 것 같다.

📍도전과제

나뉘어진 폴더에 들어간 파일들을 다시 꺼내오는 것을 해보라고 하셨다.

import os
import shutil
PDF_DIR = './실습1/pdf_files/'
file_list = os.listdir(PDF_DIR)
for file in file_list:
    new_list = os.listdir(PDF_DIR + file)
    # print(new_list)
    if os.path.isdir(PDF_DIR + file):
        pdfs = os.listdir(PDF_DIR + file)
        for pdf in pdfs:
            shutil.move(PDF_DIR + file + '/' + pdf, PDF_DIR + pdf)

음?
이제보니 new_list는 필요가 없다..🤔
각 폴더별로 파일들이 잘 있는지 확인하기 위해서 for문안에 적어준건데 남아있네🤷‍♀️
어쨌든! 코드 설명을 하자면 shutil.move()를 사용해줬기 때문에 pdf_files에는 날짜별로 정리된 폴더들만 남아있다.
os.path.isdir()을 이용해줘서 해당 폴더 안에 파일이 있다면 그 파일들을 변수 pdfs에 저장한다. 이후 마찬가지로 shutil.move()를 사용해서 각 날짜별 폴더 안에서 밖으로 옮겨주면 끝.
근데 반복문 안에서 os.rmdir()을 이용하여 폴더들을 지워주려고 하니까 자꾸 프로세스 충돌이 떠서 결국 코드에서 빼줬다..
그래서 직접 지워주려고 해도 사용중인 폴더라며 삭제가 불가능하길래 resmon.exe로 프로세스 강제 종료하고 지워주기를 반복했음. (근데 이 경우 커널을 다시시작하면 해결이 됨.. 여러번 파일을 만들었다 지우면 충돌이 일어나나 봄🤔)

그렇다고 반복문 밖에서 사용하면 디렉토리가 비어있지 않아서 못 씀.

근데 또!! 절대경로로는 되는데 상대경로로 안되는 경우가 있었다. (+이 경우도 커널을 다시 시작하니까 해결이 됐다..)
왜 자꾸 이런 오류가 뜨는진 모르겠지만.. 여러번 파일을 지웠다 옮겼다 만들었다 개지랄을해서 그런가보다..라고 생각하기로 함.
os.rmdir()을 사용하는 문제를 어떻게든 해결 해 보고 싶은데 어렵다 ㄱ=

profile
중요한 것은 꺾이지 않는 마음

0개의 댓글