Blog Full Notice
back to main page
Ch04. (파일 디렉터리) 업무효율 향상을 위한 폴더 관리 프로그램 만들기 네이버 블로그
motivation: 네이버 블로그
#Ch04. [파일/디렉터리] 업무효율 향상을 위한 폴더 관리 프로그램 만들기 : 네이버 블로그
1. 프로젝트 개요
개발 핵심 기능.
압축 파일 정리
파일명 정리 - 일정한 규칙으로 파일명이 되어 있어야 분류 가능
폴더 만들기 - 파일명 규칙에 맞는 폴더에 정리하는.
파일 옮기기
압축 파일 정리 - zipfile, tarfile
파일명 정리 - openpyxl
폴더 만들기 - os.path, pathlib
파일 옮기기 - glob, fnmatch, shutil
라이브러리를 보자.
2. 디렉터리 다루기
os.path, pathlib
os.path 와 pathlib 모두 파이썬에서 경로와 디렉터리를 처리할 때 자주 사용되는 내장 라이브러리
os.path 는 경로를 문자열로 다루고, pathlib 은 경로를 객체형으로 다루는 차이가 있음
pathlib 은 파이썬 3.4 버전 이후부터 지원
파일 찾기, 시스템 경로 등의 기능이 유용 (비교 전체 표)
디렉토리를 다루는 표준 라이브러리는, os라이브러리 안의 path를 이용하는 방법, pathlib이라는 라이브러리를 사용하면 된다. 두 모듈 모두, 기능은 같다.
두개의 차이점은, os.path는 경로를 문자열로 다룰 때, pathlib은 경로를 객체형으로 다룬다는 차이가 있다. 이 두개가 어떤 것이 편리하다 이게 어떤 경우에는 맞을 수 있다. 어느거를 사용해도 상관이 없다.
같은 기능을 구현하는 다른 문법이 있다고 한다.
위 링크에, 비교 전체 표가 있다고 한다.
import os
import pathlib
현재 디렉토리 확인
os.getcwd()
pathlib.Path.cwd()
경로 존재 확인
fastcampus 폴더에, directory가 있는지.
근데 dir_file 에 r’C:\Users’ 가 있는데 r이라는 것은, 윈도우 파일탐색기에서 경로를 복사를 하게 되면, 역슬레쉬가 나온다. 그런데 파이썬에서는 다 슬레쉬로 폴더 구분자를 사용한다. 슬레쉬가 아니면 오류가 난다.
r이라는 것은, 뒤에 나오는 것은 문자열이다. 이걸 표시해주는 것이다. 그래서 r이라고 하면 슬레쉬로 쓸 수가 있다. 역슬레쉬를.
dir_file = r'C:\Users\Shin-Nyum\Desktop\fastcampus\test'
print(os.path.exists(dir_file))
print(pathlib.Path.exists(pathlib.Path(dir_file)))
# print(pathlib.Path.exists(dir_file)) 하면 에러남. 그냥 그럼. str을 안받음. 문자열을 객체로 받기 때문.
디렉토리 만들기
dir_os = r'C:\Users\Shin-Nyum\Desktop\fastcampus\os\새폴더'
dir_pathlib = pathlib.Path(r'C:\Users\Shin-Nyum\Desktop\fastcampus\pathlib\새폴더')
# os
if not os.path.exists(dir_os):
os.makedirs(dir_os)
# pathlib
dir_pathlib.mkdir(parents=True, exist_ok=True)
새 디렉토리, 폴더를 만드는 법.
os를 때에는, os안에, 새폴더를 만들어보자.
pathlib에서는 pathlib안에 새폴더를 만들어보자.
os를 통해서 만들 때에는, 경로가 존재하는지 판단을 해야 한다. 그러면 이 경로가 없을 때에만, 폴더를 만드는 것이다. os.makedirs(dir_os)
저 위치로 가보자. 그럼 os 안의 새 폴더, 이 경로가 생긴 것이다. os까지 생겼다.
pathlib은 한 줄로 된다. 위에서 지정했던 것을 옵션으로 인자로 받아서 조절할 수 있다. 우리가 만들고자 하는 경로, pathlib 안에 새로운 폴더 만들고, 인자 두개. parents=False, exist_ok=True
exist_ok=True 는 경로가 없을 때만 하는 것. 그리고 parents는 참거짓값, False로 하면, 경로에, fastcampus안에 pathlib이 없다. 그럼 에러가 나온다. 그러면, pathlib에 없는데, parents=True라고 하면, 자기가 만들어서 직접 만들어준다.
파일명 확인
dir_file = r'C:\Users\Shin-Nyum\Desktop\fastcampus\Part 1. 파이썬 라이브러리를 활용한 기초 프로젝트 10개\04. [파일디렉터리] 업무효율 향상을 위한 폴더 관리 프로그램 만들기\sample'
# 전체 파일 리스트
print(os.listdir(dir_file))
# os
print(os.listdir(dir_file)[0])
# pathlib
print(pathlib.PurePath(os.listdir(dir_file)[0]).name)
상위 경로명 확인
dir_file = 'C:\\Users\\Shin-Nyum\\Desktop\\fastcampus\\Part 1. 파이썬 라이브러리를 활용한 기초 프로젝트 10개\\04. [파일디렉터리] 업무효율 향상을 위한 폴더 관리 프로그램 만들기\\sample'
# os
print(os.path.dirname(dir_file))
# pathlib
print(pathlib.PurePath(dir_file).parent)
경로 연결
# os
print(os.path.join(dir_file, 'os'))
# os
print(os.path.join(os.path.dirname(dir_file), 'os'))
# pathlib
print(pathlib.PurePath(dir_file).joinpath('pathlib'))
# pathlib
print(pathlib.PurePath(pathlib.PurePath(dir_file).parent).joinpath('pathlib'))
서로다른 경로를 연결하고 싶을 때,
자동적으로 경로가 추가가 되었다.
부모경로에 추가도 가능.
확장자 분리
file_path = os.path.basename(os.listdir(dir_file)[0])
print(file_path)
# os
print(os.path.splitext(file_path))
# pathlib
pathlib.PurePath(file_path).suffix
os에서는 basename을 사용한다. basename은 앞에 있는 경로를 제외하고, 파일에 해당하는 확장자를 포함한 파일명을 가져오겠다는 것.
이 새파일1.txt을 splitext를 사용하면,
파일 명과 확장자를 분리할 수 있다. 튜플 형태라서.
pathlib은 suffix를 붙여주면, 확장자만 바로 뽑아서 사용할 수 있다.
3. 파일 읽기, 저장 - fileinput, pickle
fileinput
fileinput 은 텍스트 파일을 읽고, 쓰고, 저장하는 기능을 더욱 편리하게 사용할 수 있게 해주는 라이브러리
여러개의 파일을 읽어서 수정할 수 있다.
"Inplace editing" 기능을 사용하면 open, close 보다 더 수정이 간편하고 직관적이다!
파일 읽고 저장하는 것은 open close로 텍스트파일 읽고 쓰고 할 수 있다. 그런데, fileinput을 쓰는 이유는, 그것보다 유용한 기능이 있기 때문. fileinput은 text file을 읽고, 쓰고 저장하는 기능은 같은데, 더 편리한 기능이 있다.
예를 들어서, 여러개의 파일을 읽어서 수정 가능
또 inplace editing기능이 있는데, 이거는 실행하는 중에, 수정할 수가 있다.
glob라는 라이브러리도 사용. 파일 탐색하는데 사용되는 라이브러리.
이 디렉토리에 어떤 파일들이 있는지 listdir를 통해서 확인해보자.
이 샘플, sample 폴더에,
glob를 이용해서, glob은 wildcard라는 규칙이 있다. 그래서 텍스트 파일이 세개가 있다.
이거를 이용해서 텍스트 파일을 3개를 동시에 읽을려고 한다. fileinput.input()은.
각각의 파일은, 30번째 줄까지 있는데, 한번에 읽을 수 있게 한다. fileinput.input()은.
import fileinput
import glob
import os
# 현재 경로 확인
os.getcwd()
# 디렉토리 확인
os.listdir(os.getcwd())
# 경로 설정
path = 'sample/'
# txt 파일 확인
glob.glob(os.path.join(path, "*.txt"))
['sample\\새파일1.txt', 'sample\\새파일2.txt', 'sample\\새파일3.txt']
with fileinput.input(glob.glob(os.path.join(path, "*.txt"))) as f:
for line in f:
print(line)
Inplace Editing
fileInput(파일 이름, inplace = True, backup = '.bak')
첫번째 줄 수정
txt_files = glob.glob(os.path.join(path, "*.txt"))
txt_files
with fileinput.input(txt_files, inplace = True) as f:
for line in f:
if f.isfirstline():
print('첫번째 줄입니다.', end='\n')
else:
print(line, end='')
검색된 줄 수정
with fileinput.input(txt_files, inplace = True) as f:
for line in f:
if line=='첫번째 줄입니다.\n':
print('1번째 줄입니다.', end='\n')
else:
print(line, end='')
이 if f.isfirstlin(): 에서의 print가, inplace = True 가 되면, write와 같은 의미다. 이렇게 하면 어떻게 될까? 3개의 파일을 같이 읽어서, 첫번째 줄을 바꾼다.
키워드 포함 라인 수정
with fileinput.input(txt_files, inplace = True) as f:
for line in f:
if '14번째' in line:
print('열네번째 줄입니다.', end='\n')
else:
print(line, end='')
텍스트 치환
with fileinput.input(txt_files, inplace = True) as f:
for line in f:
if '열네번째' in line:
print(line.replace('열네번째', '14번째'), end='')
else:
print(line, end='')
open close로 수정을 하려면, 라인을 한줄한줄 읽어서, 라인에 해당하면 변환해주면 끝이다. open close는 위에 있는 문자열. 미리 저장을 하고, 뒤에 나오는 문자열을 따로 저장해줘서, 변경된 문자열과 다시 합쳐주는 과정이 필요하다.
이런 식의 추가적인 요소를 개발해야 하는데, inplace editing하면 라인중에 검색된 것을 치환할 수 있다.
pickle
pickle 파이썬에서 사용하는 딕셔너리, 리스트, 클래스 등의 자료형을 변환 없이 그대로 파일로 저장하고 이를 불러올 때 사용하는 모듈
객체형 파일 저장
import pickle
import pickle
# 리스트형
data = ['A', 'B', 'C']
# 파일 저장
with open('list.pkl', 'wb') as f: #b를 꼭 붙여주어야 한다. byte 형식으로 읽어오겠다는 의미.
pickle.dump(data, f)
# 파일 읽기
with open("list.pkl", 'rb') as f:
data = pickle.load(f)
pickle을 이용하면 불러온 data가 다시 list가 된다.
type(data)
list
data
['A', 'B', 'C']
리스트를 파일로 저장해서 읽어오면 다시 list가 나온다. 우리가 생각하는 피클, 오이를 절여서, 통에 그 상태로 저장하듯이, 하는 것.
# 딕셔너리형
data = {}
data[1] = {'no': 1, 'subject': '안녕 피클', 'content': '피클은 매우 간단합니다.'}
# 파일 저장
with open('dictionary.pkl', 'wb') as f:
pickle.dump(data, f)
# 파일 읽기
with open("dictionary.pkl", 'rb') as f:
data = pickle.load(f)
type(data)
data
4. 파일 찾기, 복사, 이동 - glob, fnmatch, shutil
glob
glob 는 패턴을 이용하여 파일을 검색할 때 사용하는 모듈
파일 찾는 가장 많이 쓰는 모듈은, glob라는 표준 라이브러리다.
파일의 특정 패턴이 있으면 가능.
import glob
import os
# 현재 디렉토리 확인
os.getcwd()
# txt 파일 찾기 - 현재 경로
for filename in glob.glob("*.txt"): #*는 wildcard의 의미.
print(filename)
org_data.txt
# txt 파일 찾기 - 하위 경로
for filename in glob.glob("**/*.txt"):
print(filename)
fuzzy_folder\단축키모음.txt
fuzzy_folder\부장님지시사항_220910.txt
sample\새파일1.txt
sample\새파일2.txt
sample\새파일3.txt
# txt 파일 찾기 - 현재와 하위 경로 모두 포함
for filename in glob.glob("**/*.txt", recursive=True):
print(filename)
org_data.txt
clean_folder\기타\단축키모음.txt
clean_folder\기타\부장님지시사항_220910.txt
fuzzy_folder\단축키모음.txt
fuzzy_folder\부장님지시사항_220910.txt
sample\새파일1.txt
sample\새파일2.txt
sample\새파일3.txt
파일명 글자수로 찾기
# 글자수 4
for filename in glob.glob("????.*", recursive=True):
print(filename)
# 글자수 10
for filename in glob.glob("??????????.*", recursive=True):
print(filename)
문자열 포함 파일명 찾기
#패턴을 이용해서 찾는 방법
#a-z로 이루어진 4글자짜리 파일을 찾아줘.
for filename in glob.glob("**/[a-z][a-z][a-z][a-z].*", recursive=True):
print(filename)
for filename in glob.glob("**/새파일*.*", recursive=True):
print(filename)
새파일1.txt
sample\새파일1.txt
sample\새파일2.txt
sample\새파일3.txt
for filename in glob.glob("**/*프로젝트*.*", recursive=True):
print(filename)
01. 프로젝트 개요.pptx
06. 프로젝트 실습.ipynb
06. 프로젝트 실습.py
fnmatch
fnmatch 는 glob 와 동일하게 특정한 패턴을 따르는 파일명을 찾아주는 모듈입니다.
파일명 매칭 여부를 True, False 형태로 반환하기 때문에 os.listdir() 함수와 함께 사용하는 것이 특징입니다
import fnmatch
import os
탐색 조건
파일명은 '새'로 시작한다.
확장자는 텍스트 파일을 의미하는 .txt 이다.
확장자를 제외한 파일명의 길이는 4이다.
파일명의 마지막 문자는 숫자이다.
for filename in os.listdir('./sample'):
if fnmatch.fnmatch(filename, '새??[0-9].txt'):
print(filename)
shutil
shutil 은 파일을 복사하거나 이동할때 사용하는 내장 모듈입니다.
copy, copy2 : 파일 복사
move : 파일 이동, 확장자 변경
import shutil
# 파일 복사하기
shutil.copy("./sample/새파일1.txt", "./sample/새파일1_복사본.txt")
# 메타정보 복사 #파일이 가지고 있는 내용 뿐만 아니라, 파일이 가지고 있는 수정한 날짜, 언제 생성이 되었는지. 이런 메타정보까지 복사가 되는 것. copy는 파일이 생성된 시간이 다르다. 근데 copy2는 같다.
shutil.copy2("./sample/새파일1.txt", "./sample/새파일1_복사본_메타.txt")
# 확장자 바꾸기
shutil.move("./sample/새파일1_복사본.txt", "./sample/새파일1_복사본.py")
# 확장자 바꾸기
shutil.move("./sample/새파일1_복사본.py", "./sample/새파일1_복사본.txt")
# 파일 이동하기 # 인자1: 이전 경로, 인자2: 이동할 경로
shutil.move("./sample/새파일1_복사본.txt", "새파일1_복사본.txt")
shutil.move("./sample/새파일1_복사본_메타.txt", "새파일1_복사본_메타.txt")
5. 파일 압축 - zlib, gzip, zipfile, tarfile
데이터 압축이 필요한 이유?
데이터 전송 시 대용량 데이터는 전송 속도가 느리며, 전송 문제가 발생할 가능성이 높음
데이터 압축의 종류
무손실 압축 : 데이터 손실이 전혀 없는 압축
손실 압축 : 사람이 눈치채지 못할 수준의 정보만 버리고 압축하는 방법
압축률 : 원시 자료량 (원래 데이터 크기) / 압축된 자료량 (압축된 데이터 크기)
다양한 압축 알고리즘에 따라 압축 성능 및 시간이 좌우됨
압축 : 인코딩 (Encoding)
압축 해제 : 디코딩 (Decoding)
런 - 길이 부호화 (Run-Length Encoding)
대표적인 무손실 압축 방법
긴 문자열을 압축하고 싶다. 이럴 때, A4개, B5개, C몇개. 이렇게 숫자로 바꿔주는 것이다. 앞에. 이렇게 줄여주는 것이다. 이렇게 하면 용량이 준다. 대신에, 정보를 다 가지고 있으니깐, 원본을 복호화, 디코딩 할 수 있다.
파이썬 라이브러리에서는, 압축 표준 라이브러리가 제트립이다.
zlib
zlib 은 zlib은 데이터를 압축하거나 해제할 때 사용하는 모듈
compress()와 decompress() 함수로 문자열을 압축하거나 해제
데이터 크기를 줄여서 전송이 필요할 경우 사용
import zlib
# 대용량 문자열 데이터 (350,000 byte)
data = "Life is too short, You need python." * 10000
print(len(data))
350000
그러면 문자열이 10000배 되면, 35만 byte가 된다.
zlib 압축
# 유니코드로 인코딩 후 압축
compress_data = zlib.compress(data.encode(encoding='utf-8'))
print(len(compress_data))
1077
compress_data
보면, 압축 알고리즘을 따라서, 변했다. 압축 알고리즘을 타서 나온 것. 이 data는 알아볼 수는 없지만, 용량은 확인할 수 있다. 1077byte.
# 압축률
print(f'zlib : {round(len(data) / len(compress_data), 2)}')
zlib : 324.98
325배 압축이 되었다.
해제를 할 때에는
zlib 압축 해제
org_data = zlib.decompress(compress_data).decode('utf-8')
print(len(org_data))
350000
decompress하면 된다.
org_data
gzip
gzip 은 파일을 압축하거나 해제할 때 사용하는 모듈
내부적으로 zlib 알고리즘을 사용
import gzip
# 대용량 문자열 데이터 (350,000 byte)
data = "Life is too short, You need python." * 10000
# 원본 데이터 저장
with open('org_data.txt', 'w') as f:
f.write(data)
gzip 압축
with gzip.open('compressed.txt.gz', 'wb') as f:
f.write(data.encode('utf-8'))
gzip 압축 해제
with gzip.open('compressed.txt.gz', 'rb') as f:
org_data = f.read().decode('utf-8')
org_data
zipfile
zipfile 은 여러개 파일을 zip 확장자로 합쳐서 압축할 때 사용하는 모듈
# 압축 알고리즘이 다르다.
import zipfile
# 파일 합치기
with zipfile.ZipFile('./sample/새파일.zip', 'w') as myzip:
myzip.write('./sample/새파일1.txt')
myzip.write('./sample/새파일2.txt')
myzip.write('./sample/새파일3.txt')
# 압축 해제하기
with zipfile.ZipFile('./sample/새파일.zip') as myzip:
myzip.extractall()
tarfile
tarfile 은 여러개 파일을 tar 확장자로 합쳐서 압축할 때 사용하는 모듈
import tarfile
# 파일 합치기
with tarfile.open('./sample/새파일.tar', 'w') as mytar:
mytar.add('./sample/새파일1.txt')
mytar.add('./sample/새파일2.txt')
mytar.add('./sample/새파일3.txt')
# 압축 해제하기
with tarfile.open('./sample/새파일.tar') as mytar:
mytar.extractall()
이렇게 압축 파일을 다뤄보았다.
6. 프로젝트 실습, 폴더관리 프로그램 만들기
진행 순서
압축 파일 정리
파일명 정리
폴더 생성
파일 분류 및 이동
4-6-1. 압축 파일 정리
import os
os.getcwd() #현재 jupyter notebook이 파일 경로를 잘 보고 있는지 확인
# 정리 대상 폴더 경로 지정 #pdf, csv, txt, png, zip 파일 등이 다 있다.
trg_path = './fuzzy_folder'
# 압축 파일 확인
import glob
import os
zipf_path = []
for filename in glob.glob(os.path.join(trg_path, "**/*.zip"), recursive=True):
zipf_path.append(filename)
print(zipf_path)
['./fuzzy_folder\\센터가동현황_물류.zip']
# 압축 파일 해제
import zipfile
for zipf in zipf_path:
with zipfile.ZipFile(zipf) as myzip:
zipinfo = myzip.infolist()
for info in zipinfo:
decode_name = info.filename.encode('cp437').decode('euc-kr') # 한글 깨짐 방지
info.filename = os.path.join(trg_path, decode_name)
myzip.extract(info)
한글명이 포함되어 있어서, zipfile을 사용하는데, 한글깨짐 현상이 있다. 그래서 인코딩하고 한글로 디코딩 하는 구문이 추가된 것이다.
(http://egloos.zum.com/nemonein/v/5203156)
이거를 실행시키면, 압축 파일 안에 있는 파일들이 생겼다.
4-6-2. 파일명 정리
conda activate fastcampus
pip install openpyxl #엑셀파일을 파이썬에서 다룰 수 있게 만드는 라이브러리
설치가 되었고, 실행.
import openpyxl as op
파일명 수정 시트 만들기
#폴더별 파일명 받아 엑셀파일에 작성하는 함수
def getFileName(trg_path):
#여러 폴더가 있는 폴더경로를 입력받아 list화 한다.
folderlist = os.listdir(trg_path)
#openpyxl Workbook 생성
wb = op.Workbook()
#새로 생성한 Workbook의 활성화 시트를 ws로 정의 #worksheet가 활성화되는 개념.
ws = wb.active
i=2
current_folder = trg_path #현재 폴더 위치
filelist = os.listdir(current_folder) #현재 폴더 위치의 파일들을 리스트화
#현재 폴더 위치의 리스트화 된 파일을 다시 for문을 통해 접근
for fname in filelist:
ws.cell(row=i, column=1).value = current_folder + "/" #i행 1열에 현재 폴더 경로 입력
ws.cell(row=i, column=2).value = fname #i행 2열에 파일명(변경전) 입력
i=i+1
ws.cell(row=1,column=1).value = "파일경로"
ws.cell(row=1,column=2).value = "파일명(변경전)"
ws.cell(row=1,column=3).value = "파일명(변경후)"
#위에서 작성 된 엑셀파일을 filelist.xlsx라는 이름으로 저장
wb.save(os.path.join(trg_path, "filelist.xlsx"))
# 함수 실행
getFileName(trg_path)
함수 실행하면 엑셀 파일이 하나 만들어진다. 첫번째 column에는 폴더명, 두번쨰 컬럼에는 변경하기 전 파일명이 있다. 3번째 컬럼에는 바꾸고 싶은 것을 적어주자.
그리고 저장.
파일명 변경하기
이 시트 기반으로 파일명을 변경을 해보자.
# 엑셀을 읽어오는 함수. 엑셀 파일 읽어오자. 활성화된 시트, ws 활성화하고, 그리고 첫번쨰 컬럼을 folderpath, 두번째 컬럼은 변경전, 세번쨰를 변경후파일로 저장하자. 그리고, datalist를 또 저장하다. 이렇게 만드는 이유가, 이것을 바탕으로 파일명을 변경하기 위해서, 그리고 tuple 형태로 저장한 다음 return해준다.
def excelRead(filepath : str) -> tuple:
#filelist.xlsx 경로를 받아 workbook 객체 생성
wb = op.load_workbook(filepath)
#활성화 된 시트 ws로 정의
ws = wb.active
#리스트 컴프리헨션 구문을 통해 각 열의 데이터를 리스트화하기
folderpath = [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] #변경후 파일명 리스트화
len_num = len(folderpath) #for문을 위한 열 개수 구하기(folderpath 개수)
datalist = [] #빈 리스트 생성
for i in range(1, len_num):
temp_tuple = (folderpath[i], file_before[i], file_after[i]) #임시 튜플 생성(각 행 데이터)
datalist.append(temp_tuple) #위 튜플을 datalist에 추가
return datalist # datalist 리턴
# 함수 실행
rename_list = excelRead(os.path.join(trg_path, "filelist.xlsx"))
print(rename_list)
#파일명 변경하자. fileRename. datalist에 있는 것들을, 각각의 요소 뽑아와서, 두번째 요소의 파일 명을 세번쨰 요소의 파일 명을 바꾸고, shutil.move(변경전, 변경후 파일명) 하고, 함수 실행.
import shutil
def fileRename(datalist : list):
for data in datalist:
print(data[1]+"의 파일명을"+data[2]+"로 변경합니다.")
#data[0] : 폴더경로, data[1] : 변경전 파일명, data[2] : 변경 후 파일명
shutil.move(data[0]+data[1], data[0]+data[2])
# 함수 실행
fileRename(rename_list)
실행 하고, 잘 변경되었는지 보자.
4-6-3. 폴더 생성
import fnmatch
# 파일명을 읽어와서 파일명의 분류 부분을 중복없이 리스트화
def categoryList(trg_path : str)->list :
#glob를 사용해도 되는데, 패턴에 맞는 파일들만 사용할 것이다. 부서, 패턴. 정확하게 패턴과 맞게, 규칙적인 패턴을 따르는 패턴만 분류하는 것. 우리가 분류하는 부서로 하겠다. 뒤에서 두번쨰 요소가 카테고리의 기준이 된다. 언더바 기준으로 뒤에서 두번쨰가. 그래서 split한 다음, -2 index를 category에 추가하는 것.
# 파일명 끝자리가 _XXX (숫자 세자리) 로 끝나는 파일 탐색
file_list=[]
for filename in os.listdir(trg_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("_") #파일명중 "_"로 분리하여 리스트화
category.append(temp_list[-2]) #리스트의 -2 인덱싱 데이터를 category에 추가
temp_set = set(category) #중복을 제거하기 위해 set 사용
result = list(temp_set) #중복 제거 후 다시 리스트화
return result #결과 리턴
categoryList(trg_path)
['물류', '마케팅', '인사', '재무', '생산']
#두번째에 있던 부서.
근데 패턴이 규칙적이진 않지만, 버리면 안되는 폴더가 있다. 이거는 기타로 분류하겠다.
# 함수 실행
categorylist = categoryList(trg_path) + ['기타']
print(categorylist)
import pathlib #폴더를 만들 때 사용하는 것. 새로운 폴더를 fuzzy_folder와 같은 수준에서, clean_folder를 만들어서, 정리할 것이다.
# 분류 리스트를 받아와서 정해진 위치에 폴더 생성
clean_path = './clean_folder'
def makeFolder(clean_path : str, categorylist : list):
for category in categorylist: #categorylist에 해당하는 폴더명으로 폴더를 만드는 것이다.
new_folder = pathlib.Path(os.path.join(clean_path, category))
new_folder.mkdir(parents=True, exist_ok=True)
이렇게 해서 실행하면,
# 함수 실행
makeFolder(clean_path, categorylist)
실행하면, cleanfolder가 만들어지고, 그 안에 기타, 마케팅, 물류 등의 폴더가 만들어져 있다.
4-6-4. 파일 분류 및 이동
# 폴더까지 다 만들었기 때문에, 폴더 패턴/기준에 맞춰서 파일을 이동해보자.
import shutil
#파일을 폴더 분류에 맞게 이동
def moveFile(clean_path, trg_path, categorylist): #clean에서 target path로 이동하는데, categorylist를 참조하는 것이다.
folderlist = os.listdir(clean_path) #이동시킬 경로에 생성된 분류별 폴더 리스트화
filelist = os.listdir(trg_path) #이동시킬 파일명들을 리스트화
categorydict = {} #빈 딕셔너리 생성
#파일명에 대한 폴더명을 딕셔너리로 저장
for file in filelist:
# 파일명 규칙에 맞지 않으면 '기타' 폴더로 분류
try:
temp_list = file.split("_")
assert temp_list[-2] in categorylist # 카테고리가 맞지 않으면 에러 발생
categorydict[file]=temp_list[-2] # {'파일명' : '분류'} 형태의 딕셔너리 생성
except:
categorydict[file]='기타'
#딕셔너리 정보 활용하여 파일 이동
for key, value in categorydict.items():
shutil.copy(trg_path+"/"+key, clean_path+"/"+value) #key는 파일명, value는 구성명
moveFile(clean_path, trg_path,categorylist)
이거를 실행하면, 폴더 보면, 다른 파일들이 옮겨진 것을 볼 수 있다.
이런 식으로, 각각의 부서에 맞는 폴더로 잘 정리가 되었다. 폴더관리 프로그램을 파이썬으로 구현을 해보았다.
이런 표준 라이브러리를 활용해서 규칙에 맞게, 프로그램을 만들 수 있다.
buffer
buffer
buffer
buffer
</img>
댓글남기기