공공기관2 작업 중. _temp 몽타주(재생성가능)는 제외. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
102 lines
4.0 KiB
Python
102 lines
4.0 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""작업파일명 앞에 광역(도) 접두 — {시}.xlsx → {도}_{시}.xlsx (2026-06-01).
|
|
|
|
1) 광역_사이트맵/{도}/{N.시}/{시}.xlsx 메인 파일 rename (백업·부수파일 제외).
|
|
2) 모든 .py(_스크립트/ + 광역_사이트맵/**)에서 리터럴 '{시}.xlsx' → '{도}_{시}.xlsx' 치환.
|
|
(충남·충북 phase234 SITES 하드코딩 경로, 기관폴더 스크립트 등)
|
|
※ 동적 빌더(f'{name}.xlsx' 등 5곳)는 별도 수동 수정.
|
|
|
|
사용: python -X utf8 _rename_prefix.py dry|run
|
|
"""
|
|
import os, sys, io, re
|
|
|
|
ROOT = r'D:\01.프로젝트\DB수집'
|
|
MAP = os.path.join(ROOT, '작업파일', '광역_사이트맵')
|
|
PROVS = ['충청남도', '충청북도', '전북특별자치도', '제주특별자치도']
|
|
|
|
|
|
def build_map():
|
|
"""반환 [(도, 폴더명(N.시), 시, 기존xlsx경로, 새xlsx경로)]"""
|
|
out = []
|
|
for prov in PROVS:
|
|
pdir = os.path.join(MAP, prov)
|
|
if not os.path.isdir(pdir):
|
|
continue
|
|
for fold in sorted(os.listdir(pdir)):
|
|
fdir = os.path.join(pdir, fold)
|
|
if not os.path.isdir(fdir):
|
|
continue
|
|
si = fold.split('.', 1)[-1] # 'N.시' → 시
|
|
old = os.path.join(fdir, f'{si}.xlsx')
|
|
if os.path.exists(old):
|
|
new = os.path.join(fdir, f'{prov}_{si}.xlsx')
|
|
out.append((prov, fold, si, old, new))
|
|
return out
|
|
|
|
|
|
def py_files():
|
|
fs = []
|
|
sdir = os.path.join(ROOT, '_스크립트')
|
|
for f in os.listdir(sdir):
|
|
if f.endswith('.py'):
|
|
fs.append(os.path.join(sdir, f))
|
|
for dp, _, names in os.walk(MAP):
|
|
for n in names:
|
|
if n.endswith('.py'):
|
|
fs.append(os.path.join(dp, n))
|
|
return fs
|
|
|
|
|
|
def main():
|
|
mode = sys.argv[1] if len(sys.argv) > 1 else 'dry'
|
|
m = build_map()
|
|
# 시→도 (리터럴 치환용). 시명 길이 내림차순(부분일치 방지)
|
|
s2p = {si: prov for prov, fold, si, o, n in m}
|
|
print(f'== rename 대상 {len(m)}개 ==')
|
|
for prov, fold, si, o, n in m:
|
|
print(f' {prov}/{fold}/{si}.xlsx → {prov}_{si}.xlsx')
|
|
if mode == 'run':
|
|
if os.path.exists(n):
|
|
print(' !! 이미 존재, 스킵'); continue
|
|
os.rename(o, n)
|
|
# 리터럴 치환
|
|
print('\n== .py 리터럴 치환 ==')
|
|
keys = sorted(s2p.keys(), key=len, reverse=True)
|
|
total_files = 0; total_hits = 0
|
|
for fp in py_files():
|
|
try:
|
|
txt = io.open(fp, encoding='utf-8').read()
|
|
except Exception:
|
|
continue
|
|
orig = txt; hits = 0
|
|
for si in keys:
|
|
prov = s2p[si]
|
|
pat = si + '.xlsx'
|
|
rep = f'{prov}_{si}.xlsx'
|
|
# 이미 접두된 경우 중복 방지: {prov}_{si}.xlsx 는 건드리지 않음
|
|
# 음수 룩비하인드로 바로 앞이 '_'(도접두 직후)나 한글이면 스킵
|
|
def _sub(mo):
|
|
start = mo.start()
|
|
before = txt[max(0, start - 1):start]
|
|
# 직전이 '_' 또는 한글(다른 시명 꼬리)이면 치환 안 함
|
|
if before and (before == '_' or '가' <= before <= '힣'):
|
|
return mo.group(0)
|
|
return rep
|
|
new = re.sub(re.escape(pat), _sub, txt)
|
|
if new != txt:
|
|
hits += new.count(rep) - orig.count(rep)
|
|
txt = new
|
|
if txt != orig:
|
|
total_files += 1
|
|
n_changed = sum(txt.count(f'{s2p[si]}_{si}.xlsx') for si in keys) - sum(orig.count(f'{s2p[si]}_{si}.xlsx') for si in keys)
|
|
print(f' {os.path.relpath(fp, ROOT)} (+{n_changed})')
|
|
total_hits += n_changed
|
|
if mode == 'run':
|
|
io.open(fp, 'w', encoding='utf-8').write(txt)
|
|
print(f'\n치환 파일 {total_files}개, 경로 {total_hits}건 ({mode})')
|
|
print('※ 동적 빌더 수동수정 필요: _dedup_all.py xpath, _tab_batch.py xlsx_path, _jeonbuk_phase234_all.py site(), phase1 3개')
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|