수만 개의 파일명 순식간에 바꾸는 마법 같은 파이썬 한 줄 코드의 비밀
📋 목차
- 📋 목차
- 작업 환경 설정과 실수 방지를 위한 안전장치
- 리스트 컴프리헨션으로 구현하는 효율적인 이름 변환
- 예외 처리와 정규 표현식의 활용
- 작업 이후 파일 정합성 검증 단계
- 운영체제와 상관없는 파일 경로 관리의 디테일
- 대량 데이터 처리 시 메모리 누수를 방지하는 제너레이터 전략
- 병렬 처리를 통한 시간 단축의 미학
- Q1. 파일명을 일괄 변경하다가 중간에 오류가 나면 어떻게 되나요?
- Q2. 파일명의 특정 순서만 바꾸고 싶은데 기존 순서가 꼬이면 어떡하죠?
- Q3. 한글 파일명이 깨지는 현상이 발생하는데 원인이 무엇인가요?
- Q4. 수만 개의 파일 이름을 바꾸기 전에 ‘미리보기’만 할 방법은 없나요?
- Q5. 파일 확장자까지 실수로 바꿔버리면 어떻게 복구하나요?
- Q6. 이미 이름이 바뀐 파일과 이름이 중복되는 경우는 어떻게 피하나요?
- Q7. 네트워크 드라이브에 있는 파일을 바꿀 때 속도가 너무 느린 이유는 무엇인가요?
- Q8. 파일 이름에 포함된 특수문자가 파이썬에서 오류를 일으킵니다
- Q9. 제너레이터 방식을 써도 속도가 만족스럽지 않습니다. 더 빠르게 할 방법은?
- Q10. 작업이 끝난 후 바뀐 파일들을 되돌리고 싶다면 어떻게 해야 하나요?
데이터 분석 프로젝트를 진행할 때마다 가장 먼저 맞닥뜨리는 지겨운 고비가 바로 수천, 수만 개의 파일 이름 정리입니다. 연도별, 날짜별로 제각각 흩어진 파일들을 하나하나 마우스로 클릭하며 이름을 바꾸던 시절, 저는 며칠 밤을 새우며 단순 반복 노동에 회의감을 느끼곤 했습니다. 사실 실무 현장에서는 프로그램 하나를 돌리기 위한 전처리 과정에서 이미 지쳐버리는 경우가 허다합니다. 처음에는 배치 파일을 써보기도 하고 유료 툴을 찾아 헤매기도 했지만, 결국 가장 빠르고 확실한 해결책은 파이썬이었습니다. 코드 몇 줄이면 운영체제에 상관없이 파일 시스템을 장악할 수 있다는 사실을 깨달은 이후, 제 업무 방식은 완전히 바뀌었습니다. 여러분도 더 이상 비효율적인 수동 작업에 소중한 시간을 낭비하지 마세요. 단 한 줄의 코드가 어떻게 수 시간의 노동을 1초의 효율로 바꾸는지, 그 현장의 기술을 지금부터 나누어 드리겠습니다.
| 구분 | 수동 작업 방식 | 파이썬 자동화 방식 |
|---|---|---|
| 처리 속도 | 수만 개 기준 수 시간 소요 | 1초 내외 즉시 처리 |
| 오류 발생률 | 사람의 실수로 인한 파일 누락 발생 | 코드 기반으로 완벽하게 균일 처리 |
| 확장성 | 파일 개수가 늘어날수록 작업 시간 급증 | 수백만 개도 동일한 시간 내 처리 |
파이썬의 내장 라이브러리인 pathlib을 활용하면 파일 시스템을 다루는 일이 훨씬 직관적으로 변합니다. 흔히 os 모듈을 많이 쓰지만, 실무에서는 객체 지향 방식으로 경로를 관리할 수 있는 pathlib이 훨씬 깔끔합니다.
수만 개의 파일 이름을 순식간에 바꿀 때 제가 가장 즐겨 쓰는 방식은 리스트 컴프리헨션을 활용한 한 줄 코드입니다. 예를 들어 특정 폴더 내의 모든 .txt 파일을 data_001.txt와 같은 형식으로 바꾸고 싶다면 터미널에서 이렇게 실행합니다.
from pathlib import Path
[f.rename(f.parent / f"data_{i:03d}{f.suffix}") for i, f in enumerate(Path('경로').glob('*.txt'))]
이 코드를 실행하는 순간, 수만 개의 파일이 눈앞에서 순식간에 정돈되는 광경을 보게 될 겁니다. 여기서 핵심은 f.rename 함수와 enumerate를 조합해 파일명에 고유한 번호를 부여하는 방식입니다. 만약 파일명이 이미 복잡하게 꼬여 있다면, f.stem을 사용하여 파일 이름만 추출한 뒤 특정 문자열을 치환하는 replace 함수를 조합해 보세요.
현장에서 이 코드를 적용할 때 주의할 점은 항상 백업본을 만들거나, 처음부터 모든 파일을 바꾸지 말고 print 문을 먼저 넣어 어떤 이름으로 변경될지 미리 확인하는 습관입니다. 저는 과거에 정규식을 잘못 써서 파일 확장자까지 꼬여버린 경험을 한 뒤로는 반드시 테스트 코드를 먼저 돌려보는 습관이 생겼습니다. 이 간단한 자동화 루틴 하나만 익혀둬도 프로젝트 전체의 완성도가 달라집니다. 이제는 귀찮은 파일 정리 업무를 파이썬에게 맡기고, 여러분은 데이터를 해석하고 가치를 창출하는 본질적인 고민에 더 많은 시간을 투자하시길 바랍니다.
작업 환경 설정과 실수 방지를 위한 안전장치
파이썬 환경에서 파일 시스템을 건드리는 작업은 언제나 신중해야 합니다. 실무에서 가장 많이 발생하는 실수는 원본 데이터를 돌이킬 수 없는 상태로 만드는 일입니다. 수만 개의 파일명 순식간에 바꾸는 마법 같은 파이썬 한 줄 코드의 비밀을 실전에서 사용하기 전, 가장 먼저 해야 할 일은 작업 대상 폴더의 전체 복사본을 만들어 두는 것입니다. 운영체제에 따라 다르지만, 파일 입출력 작업은 한 번 실행되면 되돌리기(Undo)가 불가능하기 때문입니다.
코드를 작성하기 전에 현재 작업 경로를 확인하는 습관을 들여야 합니다. pathlib의 Path.cwd()를 사용하면 현재 파이썬 스크립트가 실행되는 위치를 정확히 파악할 수 있습니다. 낯선 경로에서 무작정 코드를 실행했다가 엉뚱한 시스템 파일이나 프로젝트 라이브러리 파일까지 이름을 바꿔버리는 참사를 방지하기 위해서입니다. 작업하려는 폴더의 절대 경로를 변수에 정확히 할당하는 것만으로도 작업의 절반은 성공한 셈입니다.
본격적인 자동화에 앞서 가상 테스트를 진행하는 것도 중요합니다. 저는 항상 실제 rename 메서드를 호출하기 전에 파일의 목록만 먼저 출력해보는 습관이 있습니다. for f in Path('경로').glob('*'): print(f.name)과 같은 코드를 먼저 실행해 보면, 내가 의도한 파일들만 정확히 타겟팅하고 있는지 한눈에 확인할 수 있습니다. 이렇게 검증된 경로와 파일 객체를 확보한 상태에서 비로소 수만 개의 파일명 순식간에 바꾸는 마법 같은 파이썬 한 줄 코드의 비밀을 적용할 준비가 끝납니다.
리스트 컴프리헨션으로 구현하는 효율적인 이름 변환
파이썬의 리스트 컴프리헨션은 단순히 반복문을 줄이는 도구를 넘어, 대량의 데이터를 처리할 때 메모리 효율을 극대화하는 강력한 수단입니다. 수만 개의 파일명 순식간에 바꾸는 마법 같은 파이썬 한 줄 코드의 비밀은 바로 이 컴프리헨션 내부에서 객체지향적인 파일 경로 연산을 수행하는 것에 있습니다. 파일 시스템을 순회하며 일일이 명시적으로 for 문을 돌리는 것보다 코드가 훨씬 간결해질 뿐만 아니라 실행 흐름도 매우 직관적입니다.
실제 현업에서는 단순히 순서대로 번호를 매기는 것뿐만 아니라, 특정 키워드를 찾아서 제거하거나 날짜 형식만 추출해야 하는 경우가 많습니다. 이때 f.stem.replace('old', 'new')와 같은 방식으로 문자열을 가공하면 원하는 결과물을 아주 쉽게 얻을 수 있습니다. 파일 객체에서 stem은 확장자를 제외한 파일 이름만, suffix는 확장자만 따로 떼어주기 때문에, 확장자가 깨지지 않도록 보호하면서도 파일명만 깔끔하게 수정하는 전략이 가능해집니다.
수만 개의 파일명 순식간에 바꾸는 마법 같은 파이썬 한 줄 코드의 비밀을 제대로 활용하려면 f-string 포매팅의 정밀함이 필요합니다. {i:03d}와 같이 숫자의 자릿수를 지정해 주면, 파일 탐색기에서 정렬했을 때 파일 이름이 1, 10, 100 순서가 아니라 001, 002, 003 순서로 예쁘게 정렬됩니다. 이런 작은 디테일이 쌓여 결과물의 완성도를 결정짓고, 추후 데이터 분석 시 데이터 로드 순서를 꼬이지 않게 만들어 줍니다.
예외 처리와 정규 표현식의 활용
데이터는 항상 완벽하게 들어오지 않습니다. 폴더 안에는 우리가 바꾸고 싶지 않은 시스템 파일이나 이미 이름이 변경된 파일들이 섞여 있을 확률이 높습니다. glob 패턴을 지정할 때 *.txt처럼 명확한 확장자를 지정하거나, 특정 패턴을 가진 파일만 필터링하는 조건을 추가하는 것이 필수입니다. 만약 파일명이 복잡하게 뒤엉켜 있다면 re 모듈과 정규 표현식을 조합하여 특정 조건에 부합하는 파일만 수정하도록 제어권을 강화할 수 있습니다.
예를 들어 숫자가 포함된 파일만 골라내거나, 특정 날짜 포맷이 포함된 파일만 타겟팅하는 작업은 re.search() 메서드를 컴프리헨션의 조건절에 넣는 것만으로 가능합니다. 이렇게 하면 수천 개의 파일 중에서 내가 정확히 바꿔야 할 대상만 골라내어 연산을 수행할 수 있어 오류 발생 가능성을 극단적으로 낮출 수 있습니다. 무조건 전체를 바꾸려 하기보다는 조건을 세밀하게 다듬는 것이 실력 있는 엔지니어의 자세입니다.
또한 파일 이름 변경 작업 중 발생할 수 있는 중복 문제도 고려해야 합니다. 이미 존재하는 파일명으로 변경하려고 시도할 경우 파이썬은 즉시 에러를 뿜어냅니다. 이런 사태를 대비해 저는 항상 이름 뒤에 타임스탬프를 붙이거나, if not new_path.exists():와 같은 조건문을 활용해 충돌을 방지합니다. 이런 꼼꼼한 예외 처리를 코딩 습관으로 들이면 수만 개의 파일을 다룰 때도 당황하지 않고 안정적으로 작업을 완수할 수 있습니다.
작업 이후 파일 정합성 검증 단계
자동화가 끝났다고 해서 바로 업무를 종료해서는 안 됩니다. 파이썬이 모든 파일을 성공적으로 처리했는지 최종 확인하는 과정이 반드시 필요합니다. 작업이 완료된 후 동일한 폴더 내의 파일 개수가 이전과 일치하는지, 파일의 확장자가 손상되지 않았는지 파이썬으로 빠르게 체크해 보세요. list(Path('경로').glob('*'))의 길이를 확인하는 것만으로도 전체 작업의 누락 여부를 판단할 수 있습니다.
저는 보통 작업이 완료된 직후에 파일 목록을 텍스트 파일로 저장해 두는 방식을 선호합니다. 나중에 원본 데이터가 어떤 상태였는지 증빙해야 하거나, 특정 파일의 이름이 바뀌기 전으로 되돌려야 할 때 이 텍스트 파일이 훌륭한 로그 역할을 합니다. 업무 도구로서의 파이썬은 단순히 자동화를 해주는 것을 넘어, 결과의 이력까지 관리할 수 있게 해주는 최고의 파트너가 되어줍니다.
이제 여러분도 이 기술을 활용해 보시기 바랍니다. 마우스 클릭으로 수 시간을 허비하던 비효율의 굴레에서 벗어나, 데이터를 다루는 본질에 집중하는 시간이 늘어날 것입니다. 단순히 코드를 복사해서 쓰는 수준을 넘어, 파일 입출력의 구조를 이해하고 나만의 로직을 입히는 경험을 시작해 보세요. 이런 작은 자동화의 성공 경험이 모여 더 거대하고 복잡한 데이터 파이프라인을 구축하는 든든한 초석이 될 것입니다.
운영체제와 상관없는 파일 경로 관리의 디테일
수만 개의 파일을 다루다 보면 의외로 가장 많이 겪는 병목 구간이 운영체제별 경로 구분자 차이입니다. 윈도우는 역슬래시(\)를 쓰고, 리눅스나 맥은 슬래시(/)를 사용하죠. 파이썬을 다루면서 os.path.join이나 문자열 합치기로 경로를 만들면 서버 환경이 바뀔 때마다 코드를 수정해야 하는 번거로움이 생깁니다. 저는 12년 넘게 실무를 하면서 깨달은 가장 깔끔한 방법은 pathlib 라이브러리의 슬래시 연산자(/)를 활용하는 것입니다.
예를 들어, path_obj / 'new_name.txt'와 같이 작성하면 운영체제에 맞춰 자동으로 최적화된 경로를 생성해 줍니다. 이게 왜 중요하냐면, 수만 개의 파일을 한 번에 처리할 때 경로 문제로 발생하는 사소한 오류가 전체 프로세스를 중단시키기 때문입니다. 데이터 파이프라인을 짤 때 시스템 독립적인 코드를 작성하는 것은 엔지니어로서 갖춰야 할 아주 기초적인 태도입니다. 또한 glob 대신 rglob을 사용해 보세요. rglob('*')을 쓰면 현재 폴더뿐만 아니라 하위 폴더 전체의 파일을 재귀적으로 훑어줍니다. 폴더 구조가 복잡하게 얽혀 있는 대용량 데이터셋을 정리할 때, 이 함수 하나로 코드 양을 절반으로 줄였던 기억이 납니다.
대량 데이터 처리 시 메모리 누수를 방지하는 제너레이터 전략
수만 개의 파일을 다룰 때 리스트로 전부 불러와서 메모리에 올리는 방식은 시스템 자원을 지나치게 소모합니다. 파일 목록이 십만 단위를 넘어가면 파이썬 프로세스가 메모리 부족으로 멈추거나 시스템이 느려지는 경험을 하실 겁니다. 이를 방지하기 위한 핵심 비결은 리스트 컴프리헨션의 괄호를 대괄호([])에서 소괄호(())로 바꾸는 ‘제너레이터 표현식’을 사용하는 것입니다. 제너레이터는 한 번에 모든 데이터를 메모리에 띄우지 않고, 필요할 때마다 하나씩 값을 꺼내 처리하므로 아주 적은 메모리로도 수백만 개의 파일명을 거뜬히 바꿀 수 있습니다.
파일 처리 자동화를 설계할 때 제가 실무에서 반드시 적용하는 5가지 핵심 체크리스트는 다음과 같습니다. 이 리스트만 잘 지켜도 데이터 유실 사고를 99% 예방할 수 있습니다.
- 파일명 변경 전, 샘플 10개만 리스트업하여 결과값을 미리 화면에 출력해 보세요.
- 읽기 전용 속성을 가진 파일이 포함되어 있는지 확인하고 미리 권한을 체크하세요.
- 파일 이름에 특수문자나 공백이 포함된 경우, 운영체제별로 문제가 없는지 정규화 과정을 거치세요.
- 한 번에 너무 많은 파일 처리가 부담스럽다면,
itertools.islice를 사용해 일정 개수만큼 나누어 처리하는 배치(Batch) 방식을 권장합니다. - 변경 작업 실행 직후
os.rename의 결과값이 정상인지 확인하는 예외 처리 루틴을 반드시 넣으세요.
병렬 처리를 통한 시간 단축의 미학
단일 스레드로 수만 개의 파일명을 하나씩 바꾸는 것은 컴퓨터의 속도를 제대로 활용하지 못하는 방식입니다. 현대의 프로세서는 멀티코어 구조로 되어 있는데, 파이썬의 concurrent.futures 라이브러리를 활용하면 순식간에 속도를 3배 이상 높일 수 있습니다. ThreadPoolExecutor를 사용하여 파일 입출력 작업을 병렬로 처리하는 코드를 작성해 본 적이 있는데, 단순히 반복문을 돌리는 것과는 비교할 수 없는 효율을 보여주었습니다.
물론, 파일 시스템은 단일 자원이기 때문에 너무 많은 스레드를 띄우면 오히려 병목이 발생할 수 있습니다. 저는 보통 CPU 코어 개수와 시스템의 디스크 읽기 속도를 고려하여 4개에서 8개 정도의 워커를 띄우는 편입니다. 이런 사소한 튜닝이 쌓여서, 남들은 수 시간이 걸릴 작업을 저는 5분 만에 끝낼 수 있게 해주는 것이죠. 결국 코드는 정직합니다. 언어의 문법을 아는 것을 넘어, 컴퓨터의 구조와 파일 시스템이 작동하는 원리를 이해할 때 비로소 진정한 의미의 ‘마법 같은’ 자동화가 시작됩니다. 이제 여러분도 무조건 빠르게 코드를 짜기보다, 안전하고 효율적인 구조를 먼저 설계하는 엔지니어의 관점을 가져보시기 바랍니다. 처음에는 낯설고 어려워 보여도, 한 번 체득하면 수만 개의 파일 앞에서도 절대 당황하지 않는 스스로를 발견하게 될 것입니다.
Q1. 파일명을 일괄 변경하다가 중간에 오류가 나면 어떻게 되나요?
A: 파이썬은 중간에 예외가 발생하면 즉시 실행을 중단합니다. 이 경우 이미 이름이 바뀐 파일과 그대로 남은 파일이 섞여 버리는 ‘불완전 상태’가 될 위험이 있습니다. 이를 방지하려면 try-except 구문을 활용해 개별 파일 처리 시 에러를 로그로 기록하고, 다음 파일로 넘어가는 예외 격리 루틴을 반드시 추가해야 합니다.
Q2. 파일명의 특정 순서만 바꾸고 싶은데 기존 순서가 꼬이면 어떡하죠?
A: 운영체제는 파일 목록을 불러올 때 매번 순서가 달라질 수 있습니다. glob 객체를 호출한 뒤 반드시 sorted() 함수를 사용하여 정렬 기준을 명확히 잡아야 합니다. 파일의 생성 시간(st_ctime)이나 수정 시간(st_mtime)을 기준으로 정렬한 뒤 리스트를 생성하면 의도한 순서대로 파일명을 바꿀 수 있습니다.
Q3. 한글 파일명이 깨지는 현상이 발생하는데 원인이 무엇인가요?
A: 파이썬 3 버전은 기본적으로 UTF-8 인코딩을 사용하므로 한글 처리에 강합니다. 다만, 파일 시스템이 윈도우의 구형 인코딩(CP949) 방식을 사용할 때 문제가 생기곤 합니다. 파일 경로를 처리할 때 문자열을 직접 다루기보다는 pathlib.Path 객체를 사용하면 운영체제 내부 인코딩 변환을 파이썬이 알아서 처리해주어 깨짐 현상을 방지할 수 있습니다.
Q4. 수만 개의 파일 이름을 바꾸기 전에 ‘미리보기’만 할 방법은 없나요?
A: 당연히 있습니다. 실제 rename() 메서드를 호출하는 대신, print() 함수를 사용하여 변경 전 이름과 변경 후 이름을 나란히 출력해 보세요. print(f'Old: {f.name} -> New: {new_name}')와 같이 작성하면, 실제로 파일 시스템을 수정하지 않고도 최종 결과물이 어떻게 변할지 화면에서 완벽하게 검증할 수 있습니다.
Q5. 파일 확장자까지 실수로 바꿔버리면 어떻게 복구하나요?
A: stem과 suffix 속성을 구분하지 않고 전체 파일명 문자열을 다루면 생기는 흔한 실수입니다. 확장자를 보호하려면 반드시 f.stem으로 파일명만 추출하고, f.suffix를 다시 붙여주는 방식을 고수해야 합니다. 만약 실수했다면 파일의 ‘매직 넘버’를 확인해 원본 확장자를 추측하는 라이브러리를 써야 하는데, 이는 매우 번거로우니 작업 전 반드시 확장자 분리 로직을 검증하세요.
Q6. 이미 이름이 바뀐 파일과 이름이 중복되는 경우는 어떻게 피하나요?
A: 파일명을 바꿀 때 흔히 하는 실수는 ‘기존 파일’과 ‘바뀔 파일’의 이름이 일시적으로 충돌하는 상황입니다. 저는 이럴 때 임시 파일명(Temporary Name)을 중간에 한 번 거치는 방식을 씁니다. 예를 들어 파일명_temp.txt로 먼저 바꾼 뒤 최종 이름으로 수정하면, 파일 시스템 내부의 이름 충돌로 인한 데이터 손실 사고를 원천 차단할 수 있습니다.
Q7. 네트워크 드라이브에 있는 파일을 바꿀 때 속도가 너무 느린 이유는 무엇인가요?
A: 네트워크 경로에서의 파일 입출력은 로컬 디스크보다 훨씬 많은 비용이 발생합니다. 반복문 안에서 계속해서 파일을 읽고 쓰는 과정이 네트워크 패킷 지연을 유발하기 때문입니다. 이런 경우에는 로컬 폴더로 복사본을 가져와서 처리한 뒤 다시 업로드하거나, 네트워크 대역폭을 고려해 한 번에 처리하는 파일 개수를 조절하는 배치 단위 최적화가 필요합니다.
Q8. 파일 이름에 포함된 특수문자가 파이썬에서 오류를 일으킵니다
A: 운영체제마다 파일명으로 사용할 수 없는 문자(\, /, :, *, ?, ", <, >, |)가 정해져 있습니다. 정규 표현식 모듈인 re.sub()를 사용하여 허용되지 않는 특수문자를 빈 문자열이나 언더바(_)로 치환하는 정규화 과정을 선행하세요. 이 과정만 거쳐도 파일 시스템 접근 오류의 80%는 사라집니다.
Q9. 제너레이터 방식을 써도 속도가 만족스럽지 않습니다. 더 빠르게 할 방법은?
A: 파일 시스템 접근 자체가 병목이라면 os.scandir() 함수를 고려해보세요. glob이나 os.listdir()보다 훨씬 빠르게 디렉토리 정보를 가져옵니다. 특히 수만 개의 파일 목록을 메모리에 올리는 과정에서 발생하는 오버헤드를 획기적으로 줄일 수 있어, 대규모 데이터 처리의 속도 향상을 체감할 수 있습니다.
Q10. 작업이 끝난 후 바뀐 파일들을 되돌리고 싶다면 어떻게 해야 하나요?
A: 변경 전후의 파일명 매핑 정보를 담은 로그 파일(JSON 또는 CSV)을 생성해 두는 것이 가장 현명한 방법입니다. {"original": "old.jpg", "modified": "new.jpg"} 형태의 데이터를 JSON으로 저장해 두면, 필요할 때 이 파일을 읽어 들여 반대로 rename()을 호출하는 ‘Undo 스크립트’를 아주 간단하게 작성할 수 있습니다.
결국 수만 개의 파일 앞에서도 당황하지 않는 힘은 단순히 화려한 코드 한 줄이 아니라, 데이터의 흐름을 꿰뚫어 보는 엔지니어의 설계 철학에서 나옵니다. 지금 바로 복잡하게 얽힌 폴더를 열고, 작은 파일 몇 개부터 직접 자동화 루틴을 구축해 보시기 바랍니다. 익숙함에 안주하기보다 시스템의 원리를 이해하려는 노력이 쌓일 때, 비로소 여러분의 시간은 더 가치 있는 창의적 작업으로 채워질 것입니다. 오늘 배운 실무적 관점이 여러분의 데이터 관리 방식을 완전히 바꾸는 첫걸음이 되길 진심으로 응원합니다.