중복 파일 삭제 스크립트를 돌렸다가 식은땀 흘린 날
"거래처 이름이 변경됐는데 관련 계약서 30개를 전부 수정해야 한다", "연도가 바뀌어서 전체 보고서 템플릿의 '2025년'을 '2026년'으로 바꿔야 한다", "담당자 이름이 바뀌어서 수십 개 문서에서 일괄 교체가 필요하다"…
워드에서 Ctrl+H로 찾아 바꾸기를 한 파일씩 열어서 실행하는 방법은 파일 수가 많을수록 한계가 있습니다. 파이썬을 한 번만 세팅해두면 폴더 안의 모든 워드 파일에서 원하는 단어를 자동으로 찾아 교체하고 저장할 수 있습니다. 본문은 물론 표 안의 내용도 함께 처리합니다.
파이썬이 설치되어 있어야 합니다. 없다면 python.org에서 최신 버전을 받아 설치하세요. 설치 시 반드시 "Add Python to PATH"에 체크해야 합니다.
터미널(윈도우: CMD 또는 파워셸)을 열고 아래 명령어를 실행하세요:
pip install python-docx
python-docx는 워드(.docx) 파일을 읽고 수정하고 저장하는 라이브러리입니다. 본문 단락, 제목, 표, 머리글·바닥글까지 모두 접근할 수 있습니다.
💡 이 코드로 할 수 있는 것: 단일 워드 파일 또는 폴더 안의 모든 워드 파일에서 지정한 단어를 찾아 교체합니다. 여러 단어를 한꺼번에 교체할 수 있고, 본문·제목·표 안 텍스트를 모두 처리하며, 교체 결과를 원본에 덮어쓰거나 별도 파일로 저장할 수 있습니다.
아래 코드를 그대로 복사해서 메모장에 붙여넣고, word_replace.py로 저장하세요. 저장 시 파일 형식은 "모든 파일", 인코딩은 UTF-8로 설정합니다.
from docx import Document
from pathlib import Path
# ① 설정
FOLDER_PATH = r"C:\Users\내이름\Desktop\워드파일모음" # ← 처리할 폴더 경로
OVERWRITE = False # ← True: 원본 덮어쓰기 / False: 별도 파일로 저장
OUTPUT_SUFFIX = "_수정본" # ← OVERWRITE=False 일 때 저장 파일명 접미사
# ② 교체 규칙 (여러 개 동시 처리 가능)
REPLACE_MAP = {
"A주식회사": "B테크놀로지", # 거래처명 변경
"2025년": "2026년", # 연도 변경
"홍길동": "김철수", # 담당자 변경
# 필요한 만큼 추가 가능
}
# ③ 단락 내 텍스트 교체 함수 (서식 유지)
def replace_in_paragraph(para, replace_map):
"""단락의 서식을 유지하면서 텍스트를 교체합니다."""
replaced = False
for run in para.runs:
for old, new in replace_map.items():
if old in run.text:
run.text = run.text.replace(old, new)
replaced = True
return replaced
# ④ 워드 파일 처리 함수
def process_docx(file_path, replace_map, overwrite, suffix):
doc = Document(str(file_path))
count = 0
# 본문 단락 처리
for para in doc.paragraphs:
if replace_in_paragraph(para, replace_map):
count += 1
# 표 안의 셀 처리
for table in doc.tables:
for row in table.rows:
for cell in row.cells:
for para in cell.paragraphs:
if replace_in_paragraph(para, replace_map):
count += 1
# 머리글·바닥글 처리
for section in doc.sections:
for para in section.header.paragraphs:
if replace_in_paragraph(para, replace_map):
count += 1
for para in section.footer.paragraphs:
if replace_in_paragraph(para, replace_map):
count += 1
# 저장
if overwrite:
save_path = file_path
else:
save_path = file_path.parent / (file_path.stem + suffix + file_path.suffix)
doc.save(str(save_path))
return count, save_path
# ⑤ 폴더 안의 모든 워드 파일 처리
folder = Path(FOLDER_PATH)
docx_files = sorted(folder.glob("*.docx"))
print(f" 📂 처리할 파일: {len(docx_files)}개")
print(f" 🔄 교체 규칙: {len(REPLACE_MAP)}개\n")
if not docx_files:
print("⚠ .docx 파일을 찾을 수 없습니다. FOLDER_PATH를 확인하세요.")
else:
total_replaced = 0
for file in docx_files:
try:
count, saved = process_docx(file, REPLACE_MAP, OVERWRITE, OUTPUT_SUFFIX)
print(f" ✔ {file.name} → {saved.name} ({count}곳 교체)")
total_replaced += count
except Exception as e:
print(f" ✘ {file.name} 처리 실패: {e}")
print(f"\n✅ 완료! 총 {len(docx_files)}개 파일 / {total_replaced}곳 교체")
FOLDER_PATH에 워드 파일이 있는 폴더 경로를 입력합니다.REPLACE_MAP에 교체할 단어 쌍을 입력합니다. "찾을 단어": "바꿀 단어" 형태로 여러 개를 나열할 수 있습니다.OVERWRITE = False 상태로 먼저 실행해 결과를 확인합니다. 별도 파일(파일명_수정본.docx)이 생성됩니다. 원본에 덮어쓰려면 True로 변경합니다.python word_replace.py
정상 실행 시 터미널에 이렇게 출력됩니다:
📂 처리할 파일: 5개 🔄 교체 규칙: 3개 ✔ 계약서_A주식회사.docx → 계약서_A주식회사_수정본.docx (7곳 교체) ✔ 견적서_2025_1월.docx → 견적서_2025_1월_수정본.docx (3곳 교체) ✔ 보고서_홍길동.docx → 보고서_홍길동_수정본.docx (5곳 교체) ✔ 안내문_2025.docx → 안내문_2025_수정본.docx (2곳 교체) ✔ 업무일지_홍길동.docx → 업무일지_홍길동_수정본.docx (4곳 교체) ✅ 완료! 총 5개 파일 / 21곳 교체
오류 1: 교체가 되었는데 워드에서 열면 일부가 안 바뀐 것처럼 보임
워드는 내부적으로 텍스트를 여러 run(서식 단위)으로 나눠 저장합니다. "홍길동"이 "홍", "길", "동"으로 분리 저장된 경우 코드가 인식하지 못합니다. 이 경우 워드에서 해당 텍스트를 한 번 지우고 다시 입력한 뒤 저장하면 run이 합쳐집니다. 또는 아래 응용 섹션의 run 병합 코드를 사용하세요.
오류 2: ModuleNotFoundError: No module named 'docx'
설치 시 docx가 아닌 반드시 python-docx로 입력해야 합니다.
python -m pip install python-docx
오류 3: PermissionError
처리하려는 파일이 현재 워드에서 열려 있을 때 발생합니다. 해당 파일을 닫은 후 다시 실행하세요.
워드 내부에서 텍스트가 여러 run으로 쪼개져 있을 때도 교체할 수 있는 방법입니다. 단락 전체 텍스트를 합쳐서 교체 후 첫 번째 run에 다시 저장하고 나머지 run을 비우는 방식입니다.
def replace_in_paragraph_safe(para, replace_map):
"""run이 분리된 경우에도 교체하는 안전한 방식"""
full_text = "".join(run.text for run in para.runs)
new_text = full_text
for old, new in replace_map.items():
new_text = new_text.replace(old, new)
if new_text != full_text and para.runs:
para.runs[0].text = new_text
for run in para.runs[1:]:
run.text = ""
return True
return False
이 함수로 코드 ③의 replace_in_paragraph를 교체하면 run 분리 문제가 해결됩니다. 단, 서식(굵기, 색상 등)이 첫 번째 run의 서식으로 통일됩니다.
💡 이전 게시글과 결합하면: 워드 문서 자동 생성 편으로 템플릿에서 문서를 만든 뒤, 이 코드로 내용을 일괄 수정하는 2단계 워드 자동화 파이프라인을 구성할 수 있습니다. ZIP 자동 압축 편과 결합하면 수정된 파일 전체를 압축해서 한 번에 전달하는 것도 가능합니다.
이 코드를 응용하면 특정 단어가 포함된 파일만 골라내거나, 교체 결과를 엑셀 로그로 남기는 것도 가능합니다.