본문 바로가기

1. Python

3/14 IT 국비교육 (9일차) / 24.파일입출력라이브러리~25.폴더관리프로그램실습

 


★ 주피터 노트북 설치 및 실행

24. 파일 입출력 라이브러리

25. 폴더 관리 프로그램 실습

 


 

 


★ 주피터 노트북 설치 및 실행

 

* '24. 파일 입출력 라이브러리', '25. 폴더 관리 프로그램 실습' :

Google Colab이 아니라 Jupyter Notebook이라는 에디터를 이용하여 진행

 

1. pip를 이용하여 설치할 예정이므로 Python 프로그램을 미리 설치.
    pip : 파이썬의 라이브러리 설치를 도와주는 환경

2. 명령프롬프트에 pip install jupyter 입력.
(설치가 되지 않을 시, 업그레이드의 문제이므로 pip install --upgrade pip 입력 후 재설치)

3. 주피터 노트북 실행.
(1) 명령프롬프트에 jupyter notebook --notebook-dir='c:\yjcho\python' 입력
(2) 명령프롬프트에 cd c:\yjcho\python 를 입력한 후, jupyter notebook 입력
  실행 후 명령프롬프트 창은 서버에 연결이 되어있기 때문에 닫으면 안됨.
  (우측 상단의 [new] -> [python 3] 실행으로 에디터 창을 띄울 수 있음.)

 


* 단축키 *

셀 선택 모드 (ESC)
+ a : 위에 새로운 셀을 추가 (like Ctrl+M A)
+ b : 아래에 새로운 셀을 추가 (like Ctrl+M B)
+ c : 셀 복사하기
+ d : 셀 붙여넣기
+ x : 셀 잘라내기
+ dd : 셀 삭제하기 (like Ctrl + M D)
+ m : 마크다운으로 변경 (like Ctrl + M M)
+ y : 코드로 변경 (like Ctrl + M Y)

셀 입력모드 (Enter)
Ctrl + Enter : 셀 실행
Shift + Enter : 셀 실행 후 아래 셀로 이동
Alt + Enter : 셀 실행 후 아래 새로운 셀 추가
Ctrl + a : 선택 셀 코드 전체 선택
Ctrl + z : 선택 셀 실행취소
Ctrl + y : 선택 셀 다시실행
Ctrl + / : 커서 위치 주석처리

 


24. 파일 입출력 라이브러리

 

 

 

24-1. 파일 읽기 및 저장하기

 

 

24-1-1. fileinput

 

텍스트 파일을 읽고, 쓰고, 저장하는 기능을 편리하게 사용할 수 있도록 해주는 python 내장 모듈.
여러 개의 파일을 읽어서 수정할 수 있음.

 

# import : 다른 모듈이나 패키지에서 함수, 클래스, 변수 등을 가져오는 키워드.

# fileinput : python에서 파일을 읽어오는 모듈.
import fileinput
import os
import glob

 

os 모듈 :

os 모듈은 Python의 내장 모듈 중 하나로, 운영체제와 상호작용하기 위한 함수들을 제공함.

os 모듈을 사용하면 파일 시스템 조작, 프로세스 생성 및 관리, 환경 변수 설정, 현재 작업 디렉토리 확인 등

운영체제와 관련된 다양한 작업을 수행할 수 있음.

 

# getcwd() : 현재 작업 디렉토리(current working directory)를 반환하는 함수. 현재 경로를 확인해준다.
os. getcwd()
'c:\\yjcho\\python' # 임의로 설정한 경로 (주로 python 공부를 할 때 사용하는 자료들을 보관하는 폴더이다.)

 

# os.listdir() : 지정된 경로(소괄호 안)에 있는 파일과 디렉토리의 리스트를 반환해주는 함수.

   디렉토리 내 파일의 확인에 사용됨.

os.listdir(os.getcwd())
['.ipynb_checkpoints',
 '24.파일 입출력 라이브러리.ipynb',
 'day1',
 'day2',
 'jupyter',
 'sample',
 'Untitled.ipynb']


# 경로 설정
path = 'sample/' # 경로는 본인이 실습을 진행할 파일이 있는 폴더를 지정

# glob : 해당 경로와 패턴에 맞는 파일을 찾아 그 이름을 리스트로 반환하는 python 내장 함수.
glob.glob(os.path.join(path, '*.txt')) # 경로인 sample 안의 모든 txt파일을 리스트로 반환
['sample\\새파일1.txt',
 'sample\\새파일2.txt',
 'sample\\새파일3.txt',
 'sample\\새파일4.txt']
with fileinput.input(glob.glob(os.path.join(path, '*.txt'))) as f:
    for line in f:
        print(line)
# 에러가 발생할 수 있음.

    UnicodeDecodeError: 'cp949' codec can't decode byte 0x84 in position 10: illegal multibyte sequence
#인코딩 방식에 따른 오류가 발생했다는 의미.

# '다른이름으로 저장'에서 UTF-8을 ANSI로 바꿔주어야 정상적으로 작동함.
첫번째 줄입니다
2번째 줄 입니다.
3번째 줄 입니다.
첫번째 줄입니다
5번째 줄 입니다.
6번째 줄 입니다.
첫번째 줄입니다
8번째 줄 입니다.
9번째 줄 입니다.
첫번째 줄입니다
8번째 줄 입니다.
12번째 줄입니다.

 

# txt_file의 정의

txt_files = glob.glob(os.path.join(path, '*.txt'))

txt_files


# 각 파일의 첫번째 라인을 찾아 변경하기
with fileinput.input(txt_files, inplace=True) as f: # inplace : 덮어쓰겠다는 의미
    for line in f:
        if f.isfirstline(): # isfirstline() : 첫번째 line인지 아닌지를 물어보는 메서드
            print('첫번째 라인입니다.', end='\n')
        else:
            print(line, end='')           
# 실행 후 모든 txt 파일을 열었을 때, 첫번째 줄을 '첫번째 라인입니다.' 로 변경한 상황.

# 검색된 라인을 변경하기
with fileinput.input(txt_files, inplace=True) as f:
    for line in f:
        if line == '첫번째 라인입니다.\n':
            print('1번째 라인입니다', end='\n')
        else:
            print(line, end='')

# 첫번째 줄인 '첫번째 라인입니다.'를 '1번째 라인입니다.'로 변경한 상황.

 


# 키워드를 포함한 라인을 변경하기
with fileinput.input(txt_files, inplace=True) as f:
    for line in f:
        if '1번째' in line: # line 안에 '1번째'라는 키워드를 한 줄씩 확인하여 찾는 상황
            print('첫번째 줄입니다', end='\n')
        else:
            print(line, end='')

# 텍스트 치환하기
with fileinput.input(txt_files, inplace=True) as f:
    for line in f:
        if '12번째' in line: # line 안에 '12번째'라는 키워드를 한 줄씩 확인하여 찾는 상황
            print(line.replace('12번째', '열두번째'), end='') # replace()라는 메서드 사용.
        else:
            print(line, end='')

 


24-1-2. pickle


파이썬에서 사용하는 딕셔너리, 리스트, 클래스 등의 자료형을 변환없이 그대로 파일로 저장하고 불러올 때 사용하는 모듈.

import pickle

# 리스트로 저장하는 방법
list = [ ]
data = ['apple', 'banana', 'orange']

# 리스트 파일 저장

with open('list.pkl', 'wb') as f: # wb : 바이너리의 쓰기 모드
    pickle.dump(data, f) # list.pkl이 폴더 안에 생성된 것을 확인할 수 있음.
# dump() : python의 pickle 모듈에서 제공하는 함수 중 하나. 객체를 직렬화하여 파일로 저장하는 기능을 수행.

 

.pkl 확장자

python에서 객체를 직렬화(serialization)하는 데 사용되는 파일 형식 중 하나.


# 리스트 파일 읽기
with open('list.pkl', 'rb') as f: # rb : 바이너리의 읽기 모드
    data = pickle.load(f)

type(data)
list

print(data) # type이 list이므로 list로 출력되는 것을 확인할 수 있음.
['apple', 'banana', 'orange']

# 딕셔너리로 저장하는 방법
data = { }
data[1] = {'id':1, 'userid':'apple', 'name':'김사과', 'gender':'여자', 'age':20}

# 딕셔너리 파일 저장
with open('dict.pkl', 'wb') as f:
    pickle.dump(data, f)

# 딕셔너리 파일 읽기
with open('dict.pkl', 'rb') as f:
    data = pickle.load(f)

type(data)
dict

print(data)  # type이 dict이므로 dict로 출력되는 것을 확인할 수 있음.
{1: {'id': 1, 'userid': 'apple', 'name': '김사과', 'gender': '여자', 'age': 20}}

 

 


24-2. 파일 찾기, 복사, 이동하기

 


24-2-1. 파일 확장자로 찾기

os.getcwd()
'c:\\yjcho\\python'

for filename in glob.glob('*.txt'): # 디렉토리 안의 txt파일을 찾아 파일명을 출력
    print(filename)
주피터노트북.txt

# 하위 경로에서 txt파일 찾기
for filename in glob.glob('**/*.txt'):
    print(filename)
day1\Day1.txt
day1\새 텍스트 문서.txt
jupyter\test.txt
sample\새파일1.txt
sample\새파일2.txt
sample\새파일3.txt
sample\새파일4.txt

# 현재 및 하위 경로를 모두 포함해서 txt파일 찾기
for filename in glob.glob('**/*.txt', recursive=True): # recursive=True : 현재 및 하위 경로 모두 포함
    print(filename)
주피터노트북.txt
day1\Day1.txt
day1\새 텍스트 문서.txt
day1\myvenv\Lib\site-packages\certifi-2022.12.7.dist-info\top_level.txt
day1\myvenv\Lib\site-packages\charset_normalizer-3.0.1.dist-info\entry_points.txt
day1\myvenv\Lib\site-packages\charset_normalizer-3.0.1.dist-info\top_level.txt
day1\myvenv\Lib\site-packages\pip\_vendor\vendor.txt
day1\myvenv\Lib\site-packages\pip-20.2.1.dist-info\entry_points.txt
day1\myvenv\Lib\site-packages\pip-20.2.1.dist-info\LICENSE.txt
day1\myvenv\Lib\site-packages\pip-20.2.1.dist-info\top_level.txt
day1\myvenv\Lib\site-packages\requests-2.28.2.dist-info\top_level.txt
day1\myvenv\Lib\site-packages\setuptools-49.2.1.dist-info\dependency_links.txt
day1\myvenv\Lib\site-packages\setuptools-49.2.1.dist-info\entry_points.txt
day1\myvenv\Lib\site-packages\setuptools-49.2.1.dist-info\top_level.txt
day1\myvenv\Lib\site-packages\urllib3-1.26.14.dist-info\LICENSE.txt
day1\myvenv\Lib\site-packages\urllib3-1.26.14.dist-info\top_level.txt
jupyter\test.txt
sample\새파일1.txt
sample\새파일2.txt
sample\새파일3.txt
sample\새파일4.txt

 


24-2-2. 파일명 글자 수로 찾기

for filename in glob.glob('????.*', recursive=True): # ????.* : 글자 수 4개인 파일명에 확장자는 상관없음.
    print(filename)
dict.pkl
list.pkl

for filename in glob.glob('??????.*', recursive=True):
    print(filename)
주피터노트북.txt

 


24-2-3. 문자열 패턴을 포함한 파일명 찾기

for filename in glob.glob('[a-z][a-z][a-z][a-z].*', recursive=True): 

# [a-z][a-z][a-z][a-z] : 알파벳 글자 수 4개인 파일명에 확장자는 상관없음.
    print(filename)
dict.pkl
list.pkl

for filename in glob.glob('**/새파일*.*', recursive=True): # **/새파일*.* : 새파일'로 시작하는 모든 파일명
    print(filename)
sample\새파일1.txt
sample\새파일2.txt
sample\새파일3.txt
sample\새파일4.txt

for filename in glob.glob('**/*프로젝트*.*'):
    print(filename)
project\25.프로젝트 실습.ipynb
project\프로젝트.txt

 


24-2-4. fnmatch


glob과 동일하게 특정한 패턴을 따르는 파일명을 찾아주는 모듈.
파일명 매칭 여부를 True, False 형태로 반환하기 때문에 os.listdir() 함수와 함께 사용함.
# os.listdir() : 지정된 경로(소괄호 안)에 있는 파일과 디렉토리의 리스트를 반환해주는 함수.

   디렉토리 내 파일의 확인에 사용된다.


import fnmatch

# 파일명은 '새'로 시작하고, 확장명은 .txt를 검색
# 확장자를 제외한 파일명의 길이는 4개이며, 파일명의 마지막 문자는 숫자임.
for filename in os.listdir('./sample'):
    if fnmatch.fnmatch(filename, '새??[0-9].txt'): # 새??[0-9].txt : 위의 조건
        print(filename)
새파일1.txt
새파일2.txt
새파일3.txt
새파일4.txt



24-2-5. shutil


파일을 복사하거나 이동할 때 사용하는 내장 모듈.

import shutil

# 파일 복사하기.
shutil.copy('./sample/새파일1.txt', './sample/새파일1_복사본.txt')
'./sample/새파일1_복사본.txt'

# 파일 이동하기.
shutil.move('./sample/새파일1_복사본.txt', './새파일1_복사본.txt')
'./새파일1_복사본.txt'

# 확장자 변경하기.
shutil.move('./sample/새파일1_복사본.txt','./sample/새파일1_복사본.py') 

# 같은 위치로 이동을 한다는 것은 덮어쓰기의 효과가 있음.
# txt를 py로 확장자 변경하는 상황.
'./sample/새파일1_복사본.py'

 

 


24-3. 파일 압축하기

 


24-3-1. 데이터 압축


* 대용량의 데이터 및 대량의 파일을 전송할 때는 전송 속도가 느리며 전송 문제가 발생할 가능성이 매우 높음.
* 데이터 압축의 종류
    - 손실 압축 : 사람이 눈치채지 못할 수준의 정보만 버리는 압축.
    - 무손실 압축 : 데이터 손실이 전혀 없는 압축.
* 압축률 : 압축된 자료량(압축된 데이터 크기) / 원시 자료량(원래 데이터 크기)
* 다양한 압축 알고리즘에 따라 압축 성능 및 시간이 좌우됨

 

* 압축 : 인코딩(Encoding)
* 압축해제 : 디코딩(Decoding)

 


24-3-2. zlib


데이터를 압축하거나 해제할 때 사용하는 모듈.
compress()와 decompress() 함수를 이용해 문자열을 압축하거나 해제할 수 있음.
데이터 크기를 줄여서 전송이 필요한 경우 사용함.

import zlib

 

 # 압축 전
data = 'Hello Python!' * 10000
print(len(data)) # 압축 전 data의 길이 : 130,000 byte
130000


# 압축 후
compress_data = zlib.compress(data.encode(encoding='utf-8'))
print(len(compress_data)) # 압축 후 data의 길이 : 293 byte
293


# 압축해제
org_data = zlib.decompress(compress_data).decode('utf-8')
print(len(org_data)) # 압축해제 후 data의 길이 : 130,000 byte
130000

 


24-3-3. gzip


파일을 압축하거나 해제할 때 사용하는 모듈.
내부적으로 zlib 알고리즘을 사용함.

import gzip

with open('org_data.txt', 'w') as f:
    f.write(data)

# org_data.txt 파일의 압축파일을 생성. (압축파일명은 copressed.txt.gz)
with gzip.open('compressed.txt.gz', 'wb') as f:    

# open()으로 압축. # compressed.txt파일의 확장명은 .gz로 함. # wb : 바이너리로 작성.
    f.write(data.encode('utf-8'))


# gzip 압축 해제
with gzip.open('compressed.txt.gz', 'rb') as f:
    org_data = f.read().decode('utf-8')
print(len(org_data))
130000

 


24-3-4. zipfile


여러 개의 파일을 zip 확장자로 합쳐서 압축할 때 사용하는 모듈.

import zipfile

# 파일을 합친 후 압축하기. (sample 폴더 안의 새파일1부터 5까지를 압축)
with zipfile.ZipFile('./sample/새파일.zip', 'w') as myzip:
    myzip.write('./sample/새파일1.txt')
    myzip.write('./sample/새파일2.txt')
    myzip.write('./sample/새파일3.txt')
    myzip.write('./sample/새파일4.txt')
    myzip.write('./sample/새파일5.txt')

# 압축 해제하기.
with zipfile.ZipFile('./sample/새파일.zip') as myzip:
    myzip.extractall()

 


24-3-5. tarfile


여러 개의 파일을 tar 확장자로 합쳐서 압축할 때 사용하는 모듈.


zipfile과 tarfile의 차이점
zipfile과 tarfile은 둘 다 여러 파일을 하나의 파일로 압축하는 데 사용되는 라이브러리임. 

그러나 이 두 가지 라이브러리는 다음과 같은 차이점이 있음.

파일 형식: zipfile은 ZIP 파일 형식으로 파일을 압축하고, tarfile은 tar 파일 형식으로 파일을 압축. 

ZIP 파일은 Windows 및 macOS와 같은 다른 운영 체제에서도 지원되는 표준 파일 형식이지만, 

tar 파일 형식은 주로 Unix 및 Linux와 같은 운영 체제에서 사용.

압축 방식: zipfile은 파일을 압축할 때 각 파일을 개별적으로 압축하고, 

tarfile은 파일을 압축하기 전에 모든 파일을 하나의 tar 아카이브 파일로 묶어둠.

압축 알고리즘: zipfile은 DEFLATE, BZIP2, LZMA 등과 같은 다양한 압축 알고리즘을 지원하지만, 

tarfile은 보통 gzip 압축 알고리즘을 사용.

파일 크기: zipfile은 각 파일을 개별적으로 압축하기 때문에 대용량 파일을 처리하는 데 적합함. 

tarfile은 모든 파일을 하나의 아카이브 파일로 묶어두기 때문에 대용량 파일을 처리할 때는 약간 더 복잡함.

따라서, 파일 형식, 압축 방식, 압축 알고리즘, 파일 크기 등의 차이점 때문에 

zipfile과 tarfile 중 어느 것을 선택할지는 상황에 따라 다름.


import tarfile

# 파일을 합친 후 압축하기. (sample 폴더 안의 새파일1부터 5까지를 압축)
with tarfile.open('./sample/새파일.tar', 'w') as mytar:
    mytar.add('./sample/새파일1.txt')
    mytar.add('./sample/새파일2.txt')
    mytar.add('./sample/새파일3.txt')
    mytar.add('./sample/새파일4.txt')
    mytar.add('./sample/새파일5.txt')

# 압축 해제하기.
with tarfile.open('./sample/새파일.tar') as mytar:
    mytar.extractall()

 

 


 

25. 폴더 관리 프로그램 실습

 

(해당 파일들이 있는 '고라니' 폴더를 이용할 예정임)

 

25-1. 압축 파일 정리하기

 


import os
os.getcwd()
'C:\\yjcho\\python'

# 정리 대상 폴더의 경로를 설정
target_path = './고라니'

# 압축 파일의 유무를 확인하기
import glob

zipfile_path = [ ]
for filename in glob.glob(os.path.join(target_path, '**/*.zip'), recursive=True):
    zipfile_path.append(filename)
    print(zipfile_path)
['./고라니\\데이터저장_물류.zip']

# 압축 파일을 해제하기
import zipfile

for filename in zipfile_path:
    with zipfile.ZipFile(filename) as myzip:
        zipinfo = myzip.infolist() # zipinfo : zip파일 안의 파일에 대한 정보
        # 이대로 print(zipinfo)를 하면 안되고, 인코딩해서 print해야 한글이 깨지지 않음.
        for info in zipinfo:
            decode_name = info.filename.encode('cp437').decode('euc-kr') # 한글 깨짐 방지
            info.filename = os.path.join(target_path, decode_name)
            myzip.extract(info)

 


25-2. 파일명 정리하기

import openpyxl as opx 

# ModuleNotFoundError: No module named 'openpyxl' 라는 오류가 뜬다면, 따로 openpyxl 모듈의 설치를 해주어야 함.

 

openpyxl :

python에서 엑셀(xlsx/xlsm) 파일을 다루기 위한 라이브러리.

이 모듈을 사용하면 파이썬 코드로 엑셀 파일을 생성하고 수정할 수 있음.


# 명령프롬프트가 주피터노트북의 서버로 사용되고 있으나, 주피터노트북에서도 새로운 모듈의 설치를 진행할 수 있음
! pip install openpyxl 


Requirement already satisfied: openpyxl in c:\users\administrator\appdata\local\programs\python\python38\lib\site-packages (3.1.2)
Requirement already satisfied: et-xmlfile in c:\users\administrator\appdata\local\programs\python\python38\lib\site-packages (from openpyxl) (1.1.0)

# 폴더별 파일명을 입력받아 엑셀파일에 저장하는 함수
def getFileName(target_path):
    
    wb = opx.Workbook() # wb : 전체 파일 # ws : 워크시트
    ws = wb.active # 새로 생성한 WorkBook의 활성화 시트를 ws로 정의함.
    
# 엑셀 워크시트에 '파일경로', '파일명(변경전)', '파일명(변경후)'를 첫 열에 작성할 예정
    ws.cell(row=1, column=1).value = '파일경로'
    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)
# 고라니 폴더 안에 filelist.xlsx파일이 생성된 것을 확인할 수 있음.

 


25-3. 파일명 변경하기

# 리스트화를 시킨 후, return하는 단계가 먼저 필요함.

def excelRead(filepath : str) -> list:
    wb = opx.load_workbook(filepath) # 엑셀파일을 로드하면 열어서 수정해줄 수 있도록 해줌.
    ws = wb.active # 엑셀 워크시트를 활성화
    
    dirpath = [r[0].value for r in ws] # dirpath라는 변수를 생성 후 리스트화.
    file_before = [r[1].value for r in ws] # 변경 전 파일명
    file_after = [r[2].value for r in ws] # 변경 후 파일명

    len_num = len(dirpath)
    datalist = [ ]
    
    for i in range(1, len_num):
        temp_tuple = (dirpath[i], file_before[i], file_after[i]) # 임시 tuple로 데이터를 저장
        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', '새파일1_복사본.txt'), ('./고라니/', '점심시간.txt', '점심시간.txt'), ('./고라니/', '주피터노트북.txt', '주피터노트북.txt')]

import shutil

def fileRename(datalist : list): 
    for data in datalist: # list구조를 받아서 처리하는 상황
        print(data[1]+'의 파일명을'+data[2]+'로 변경합니다.')
        shutil.move(data[0]+data[1], data[0]+data[2])

fileRename(rename_list) # 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의 파일명을새파일1_복사본.txt로 변경합니다.
점심시간.txt의 파일명을점심시간.txt로 변경합니다.
주피터노트북.txt의 파일명을주피터노트북.txt로 변경합니다.

 


25-4. 폴더 생성하기

import fnmatch


def categoryList(target_path : str) -> list: # categoryList라는 함수 생성
    file_list = []
    for filename in os.listdir(target_path): # target_path에 대한 디렉토리 리스트의 데이터를 filename에 입력
        if fnmatch.fnmatch(filename, '*_[0-9][0-9][0-9].*'):
            file_list.append(filename)
            
    category = []
    for file in file_list:
        temp_list = file.split('_') # file_list를 언더바(_)를 기준으로 split하여 temp_list에 입력하겠다.
        # 예) A_2022_01_13_부서로그_인사_001 는 ['A', '2022', '01', '13', '부서로그', '인사', '001']
        category.append(temp_list[-2]) 

        # 위의 예)의 list에서 '-2'의 자리에 위치한 '인사'와 같은 category의 단어들만 뽑아내겠다.
    temp_set = set(category)
    result = list(temp_set)
    return result

# 경로 안의 폴더에서 category의 list만 뽑아낼 경우
categoryList(target_path)
['인사', '클래스설계', '물류', 'ERD', '생산']

# 위의 category의 list에서 요소를 추가하고 싶은 경우 ('기타'를 추가할 예정)
categorylist = categoryList(target_path) + ['기타']
print(categorylist)
['인사', '클래스설계', '물류', 'ERD', '생산', '기타']

import pathlib

new_path = './new_dir'

def makeDir(new_path:str, categorylist:list):
    for category in categorylist:
        new_dir = pathlib.Path(os.path.join(new_path, category)) 
        # os.path.join(new_path, category) : new_path 뒤에 category의 경로를 생성함.
        new_dir.mkdir(parents=True, exist_ok=True) 
        # mkdir() : make directory. 디렉토리(폴더)를 생성하는 함수.

        # parents=True : 중간 단계의 디렉토리도 생성할 수 있는 mkdir()함수의 옵션. (순서대로의 영향을 받지 않게됨)

        # exist_ok=True : 이미 디렉토리가 존재해도 오류를 발생시키지 않는 mkdir()함수의 옵션.

makeDir(new_path, categorylist)

 


25-5. 파일 분류 및 이동하기

import shutil

def moveFile(new_path, target_path, categorylist):
    dirlist = os.listdir(new_path) # 이동시킬 경로에 생성된 분류 디렉토리의 리스트
    filelist = os.listdir(target_path) # 이동시킬 파일명의 리스트
    categorydic = {}
    
    for file in filelist:
        try:
            temp_list = file.split('_')
            assert temp_list[-2] in categorylist
            categorydic[file] = temp_list[-2]

moveFile(new_path, target_path, categorylist)

 

 


 

과제

 본인의 정리되지 않은 폴더의 파일 → 오늘 배운 내용을 이용해 정리 이전과 정리 후를 포함하는 시나리오를 구성.