Application/Python

[Python] 03. 파이썬으로 파일 이름 일괄 변경 자동화하기

devsalix 2026. 6. 11. 10:52
728x90

파이썬으로 파일 이름 일괄 변경 자동화하기

다운로드 폴더 열어보면 보고서(1).xlsx, 보고서 (2) 최종.xlsx, 보고서(10).xlsx... 이렇게 쌓여 있고, 정렬은 또 1, 10, 11, 2, 20 순으로 엉망인 상황. 다들 한 번씩 겪어보셨죠.

저는 한때 이걸 손으로 하나씩 F2 눌러서 바꿨거든요. 50개쯤 되니까 중간에 정신이 나가더라고요.

오늘 배울 건 그걸 코드 몇 줄로 끝내는 방법이에요. 그런데 한 가지 먼저 약속해주셔야 할 게 있어요. rename은 Ctrl+Z가 안 됩니다. 그래서 안전장치부터 배울 거예요.


Path.rename() 한 줄로 끝나는 python rename

지난 글에서 pathlibPath 객체를 봤죠. 거기에 rename이라는 메서드 하나만 붙이면 끝이에요.

from pathlib import Path  # 지난 글에서 친해진 친구

p = Path("보고서(1).xlsx")   # 바꿀 파일 지정
p.rename("보고서_01.xlsx")   # 새 이름으로 변경

 

진짜 한 줄이에요. 근데 이게 너무 쉬워서 위험해요. 잘못된 코드 한 번 돌리면 폴더 안 50개 파일이 한꺼번에 망가집니다. 휴지통에도 안 들어가요.

그래서 본격적으로 들어가기 전에, 작업할 폴더는 무조건 통째로 복사해서 백업해 두세요. 윈도우 탐색기에서 Ctrl+C, Ctrl+V 한 번이면 5초 걸려요. 이거 안 하고 시작했다가 우는 분들 많이 봤어요.


파일명 일괄 변경할 때 꼭 알아야 할 안전장치, dry-run

dry-run이 뭐냐면, 실제로 바꾸기 전에 print로 결과만 미리 보는 패턴이에요. 모의고사 같은 거예요. 모의고사에서 틀리는 건 괜찮잖아요.

from pathlib import Path

folder = Path(r"C:\다운로드\보고서모음")  # 작업할 폴더

for p in folder.iterdir():                # 폴더 안 파일 하나씩
    new_name = p.stem + "_정리본" + p.suffix  # 새 이름 후보 만들기
    print(f"{p.name}  →  {new_name}")     # 일단 출력만 해서 눈으로 확인

 

실행 결과:

보고서(1).xlsx  →  보고서(1)_정리본.xlsx
보고서(2).xlsx  →  보고서(2)_정리본.xlsx

 

출력 보고 "음, 이대로 가면 되겠다" 싶으면 그때 print 부분을 p.rename(p.with_name(new_name))으로 바꿔서 다시 돌리는 거예요.

저는 지금도 자동화 스크립트 짤 때 무조건 dry-run부터 만들어요. 이거 평생 쓰시게 될 패턴이에요.


시나리오 A: 보고서(1).xlsx를 보고서_01.xlsx로 정리

윈도우에서 같은 이름 저장하면 자동으로 (1), (2) 붙는 그거요. 괄호 번호를 떼어내고 _01, _02 형식으로 깔끔하게 정리해볼게요.

from pathlib import Path
import re  # 정규식 모듈

folder = Path(r"C:\다운로드\보고서모음")

for p in folder.glob("*.xlsx"):                  # xlsx만 골라서
    match = re.search(r"\((\d+)\)", p.stem)      # (숫자) 패턴 찾기
    if match:                                    # 패턴이 있으면
        number = int(match.group(1))             # 괄호 안 숫자 꺼내기
        base = re.sub(r"\s*\(\d+\)", "", p.stem) # 괄호 부분 통째로 제거
        new_name = f"{base}_{number:02d}{p.suffix}"  # 새 이름 조립
        print(f"{p.name} → {new_name}")          # dry-run
        # p.rename(p.with_name(new_name))        # 확인 후 주석 해제

 

{number:02d} 이 부분이 살짝 마법 같아요. "숫자를 두 자리로, 빈자리는 0으로 채워서"라는 뜻이거든요. 그래서 1이 01이 되고, 10은 그대로 10이 돼요. 이렇게 해야 1, 10, 11, 2 같은 정렬 지옥에서 벗어날 수 있어요.

정규식이 처음 보면 외계어 같죠. 지금은 통째로 복붙해서 쓰셔도 돼요. \((\d+)\)는 "괄호 안 숫자 잡아내라"는 뜻이라고만 알아두시면 충분합니다.


시나리오 B: 확장자 통일 (.JPG → .jpg)

핸드폰이랑 카메라 사진 섞이면 어떤 건 .JPG, 어떤 건 .jpg. 보기 거슬리죠.

from pathlib import Path

folder = Path(r"C:\사진\2025여행")

for p in folder.iterdir():
    if p.suffix == ".JPG":                    # 대문자 확장자만 골라
        new_path = p.with_suffix(".jpg")      # 확장자만 소문자로 교체
        print(f"{p.name} → {new_path.name}")  # dry-run
        # p.rename(new_path)

 

with_suffix는 확장자만 갈아끼우는 도구예요. 그런데 한 가지 함정이 있어요. 윈도우는 파일명 대소문자를 같은 걸로 봐요. IMG.JPGimg.jpg로 바꾸려고 하면 "어? 같은 이름인데?" 하고 그냥 통과시켜버려요.

확실하게 하려면 임시 이름으로 한 번 거치면 돼요.

temp = p.with_suffix(".jpg_tmp")       # 임시 확장자로
p.rename(temp)                         # 1차 변경
temp.rename(temp.with_suffix(".jpg"))  # 진짜 이름으로

 


시나리오 C: 모든 파일에 날짜 prefix 붙이기

11월 보고서들에 2025-11_ 같은 접두어 한 번에 붙이기.

from pathlib import Path

folder = Path(r"C:\업무\11월보고서")
prefix = "2025-11_"

for p in folder.iterdir():
    if p.is_file() and not p.name.startswith(prefix):  # 파일만, 이미 붙은 건 제외
        new_path = p.with_name(prefix + p.name)        # 앞에 prefix 붙이기
        print(f"{p.name} → {new_path.name}")
        # p.rename(new_path)

 

is_file()로 폴더는 제외했어요. 폴더에 prefix 붙으면 다른 프로그램이 폴더를 못 찾아서 일이 커지거든요. 그리고 startswith 체크로 이미 2025-11_가 붙은 파일은 또 안 붙게 막아놨어요. 두 번 돌려도 안전합니다.


자주 만나는 에러 두 가지

처음에 이 에러 만나면 좀 당황스러우실 거예요. 저도 그랬거든요.

FileExistsError: 새로 지으려는 이름이 폴더에 이미 있을 때 나는 에러예요. 윈도우는 같은 이름 두 개 못 두게 막아두거든요. 미리 체크하면 됩니다.

if not new_path.exists():    # 새 이름이 비어있을 때만
    p.rename(new_path)

 

PermissionError: 그 파일을 엑셀이나 PDF 뷰어로 열어둔 상태일 때 나요. 윈도우가 "지금 누가 쓰고 있어요" 하고 잠가놓은 거예요. 해당 프로그램 다 끄고 다시 돌리시면 됩니다. 아니면 try/except로 막힌 파일은 건너뛰게 해도 되고요.

for p in folder.iterdir():
    try:
        p.rename(p.with_name(prefix + p.name))
    except PermissionError:
        print(f"건너뜀(열려있음): {p.name}")
    except FileExistsError:
        print(f"건너뜀(이미 존재): {p.name}")

실습 과제

진짜 다운로드 폴더에서 바로 연습하시면 사고 납니다. 안전한 놀이터부터 만들어보세요.

from pathlib import Path

test_folder = Path(r"C:\테스트\rename연습")
test_folder.mkdir(parents=True, exist_ok=True)   # 폴더 생성
for i in range(1, 11):
    (test_folder / f"테스트({i}).txt").touch()    # 빈 파일 10개

 

이 폴더 안에서 시나리오 A 코드를 dry-run으로 돌려보세요. 출력 마음에 들면 그때 진짜 rename을 실행해보시고요. 망해도 그냥 폴더 지우고 다시 만들면 되니까 마음 편하게 실험할 수 있어요.


이름만 바꿔도 폴더가 한결 깔끔해지죠. 그런데 여기서 한 발만 더 나가면 진짜 마법이 시작돼요. 엑셀은 엑셀 폴더로, PDF는 PDF 폴더로, 이미지는 이미지 폴더로. 다운로드 폴더가 알아서 정리되는 거예요. 다음 글에서 그걸 만들어볼게요.


 


제 글이 도움이 되셨다면 댓글 & 공감 부탁드려요 😀

 

 
728x90