🔍 “특정 경로 내 수많은 폴더 속에서 zip 파일을 일일이 찾아 크기를 확인하느라 고생하시나요? Python으로 이 과정을 완전 자동화하는 방법을 알려드립니다!”
시작하며
복잡한 디렉토리 구조에서 특정 폴더(‘original’)에 있는 ZIP 파일들을 찾고 그 크기를 자동으로 정리하는 것은 시스템 관리자나 개발자들의 일상적인 작업 중 하나입니다. 수동으로 진행 시 평균 1000개 파일 기준 약 2-3시간이 소요되지만, 자동화를 통해 작업 시간을 5분 이내로 단축할 수 있습니다.
시스템 아키텍처 및 작동 원리
flowchart TD
A[사용자 입력: 검색할 루트 경로] --> B[find_zip_files 함수 실행]
B --> C{original 폴더 여부 확인}
C -->|Yes| D[ZIP 파일 검색 및 크기 확인]
C -->|No| E[다음 폴더로 이동]
D --> F[파일 정보 수집]
F --> G[save_to_excel 함수로 데이터 전달]
G --> H[Excel 파일 생성]
E --> C
style A fill:#f9f,stroke:#333,stroke-width:2px
style G fill:#bbf,stroke:#333,stroke-width:2px
style H fill:#bfb,stroke:#333,stroke-width:2px
시스템 구성 요소 분석
| 구성 요소 | 사용 기술 | 장점 |
|---|---|---|
| 경로 처리 | pathlib.Path | 운영체제 상관없이 동일하게 동작 |
| 파일 검색 | os.walk() | 모든 하위 폴더를 빠짐없이 검색 |
| 데이터 처리 | pandas DataFrame | 엑셀 변환이 간단하고 효율적 |
코드 구현 단계별 살펴보기
1. ZIP 파일 검색 기능 구현
import os
from pathlib import Path
import pandas as pd
def find_zip_files(root_path):
"""주어진 경로에서 'original' 폴더 내의 모든 zip 파일을 찾습니다."""
zip_files = []
sizes = []
root = Path(root_path) # 경로를 Path 객체로 변환
# 모든 하위 디렉토리를 순회
for folder_path, _, files in os.walk(root):
if Path(folder_path).name == 'original':
for file in files:
if file.lower().endswith('.zip'): # 대소문자 구분 없이 ZIP 파일 검색
full_path = Path(folder_path) / file
zip_files.append(str(full_path))
sizes.append(full_path.stat().st_size)
return zip_files, sizes
2. Excel 저장 기능 구현
def save_to_excel(zip_files, sizes, output_path):
"""파일 정보를 엑셀 파일로 저장합니다."""
df = pd.DataFrame({
'파일 경로': zip_files,
'파일명': [Path(f).name for f in zip_files],
'크기(바이트)': sizes,
'크기(MB)': [size / (1024 * 1024) for size in sizes] # 바이트를 MB로 변환
})
df.to_excel(output_path, index=False)
print(f"파일이 성공적으로 저장되었습니다: {output_path}")
pandas를 사용하면 데이터를 엑셀로 저장하는 게 정말 쉽습니다. 특히 파일 크기를 바이트와 MB 두 가지 단위로 함께 저장하여 사용자의 편의성을 높였습니다.
3. 메인 실행 코드 구현
def main():
# 검색할 루트 경로를 지정합니다
root_path = input("검색할 경로를 입력하세요: ")
try:
# 결과를 저장할 엑셀 파일 경로를 지정합니다
output_path = Path(root_path) / "zip_files_info.xlsx"
# zip 파일들을 찾습니다
zip_files, sizes = find_zip_files(root_path)
if not zip_files:
print("ZIP 파일을 찾을 수 없습니다.")
return
# 엑셀 파일로 저장합니다
save_to_excel(zip_files, sizes, output_path)
# 찾은 파일 수를 출력합니다
print(f"총 {len(zip_files)}개의 ZIP 파일을 찾았습니다.")
except Exception as e:
print(f"오류가 발생했습니다: {str(e)}")
성능 최적화 방안
graph TD
A[성능 최적화 전략] --> B[병렬 처리]
A --> C[메모리 최적화]
A --> D[에러 처리]
B --> E[ThreadPoolExecutor 활용]
C --> F[청크 단위 처리]
D --> G[예외 처리 강화]
style A fill:#f9f,stroke:#333,stroke-width:2px
style E fill:#bfb,stroke:#333,stroke-width:2px
style F fill:#bfb,stroke:#333,stroke-width:2px
style G fill:#bfb,stroke:#333,stroke-width:2px
1. 병렬 처리 구현
from concurrent.futures import ThreadPoolExecutor
import itertools
def optimized_find_zip_files(root_path):
"""병렬 처리를 적용한 ZIP 파일 검색 함수"""
def process_folder(folder):
results = []
sizes = []
path = Path(folder)
if path.name == 'original':
for file in path.glob('*.zip'):
results.append(str(file))
sizes.append(file.stat().st_size)
return results, sizes
with ThreadPoolExecutor() as executor:
folders = [f for f, _, _ in os.walk(root_path)]
results = list(executor.map(process_folder, folders))
# 결과 합치기
all_files, all_sizes = [], []
for files, sizes in results:
all_files.extend(files)
all_sizes.extend(sizes)
return all_files, all_sizes
2. 메모리 사용량 최적화
def save_to_excel_in_chunks(zip_files, sizes, output_path, chunk_size=1000):
"""청크 단위로 엑셀 파일 저장하기"""
writer = pd.ExcelWriter(output_path, engine='xlsxwriter')
for i in range(0, len(zip_files), chunk_size):
chunk_files = zip_files[i:i + chunk_size]
chunk_sizes = sizes[i:i + chunk_size]
df_chunk = pd.DataFrame({
'파일 경로': chunk_files,
'파일명': [Path(f).name for f in chunk_files],
'크기(바이트)': chunk_sizes,
'크기(MB)': [size / (1024 * 1024) for size in chunk_sizes]
})
if i == 0:
df_chunk.to_excel(writer, index=False)
else:
df_chunk.to_excel(writer, startrow=i+1, header=False, index=False)
writer.save()
실전 활용 팁
1. 에러 처리 강화
class ZipScanError(Exception):
"""ZIP 파일 스캔 관련 사용자 정의 예외"""
pass
def safe_scan(root_path):
"""안전한 파일 스캔 함수"""
try:
if not Path(root_path).exists():
raise ZipScanError("지정된 경로를 찾을 수 없습니다")
if not os.access(root_path, os.R_OK):
raise ZipScanError("경로에 대한 읽기 권한이 없습니다")
return find_zip_files(root_path)
except Exception as e:
print(f"오류 발생: {str(e)}")
return [], []
2. 진행 상황 모니터링
from tqdm import tqdm
def find_zip_files_with_progress(root_path):
"""진행 상황을 보여주는 ZIP 파일 검색 함수"""
zip_files = []
sizes = []
# 전체 폴더 수 계산
folders = list(os.walk(root_path))
for folder_path, _, files in tqdm(folders, desc="폴더 검색 중"):
if Path(folder_path).name == 'original':
for file in files:
if file.lower().endswith('.zip'):
full_path = Path(folder_path) / file
zip_files.append(str(full_path))
sizes.append(full_path.stat().st_size)
return zip_files, sizes
전체 코드 모음
전체 코드를 하나의 파일(zip_file_manager.py)로 정리하면 다음과 같습니다:
# zip_file_manager.py
import os
from pathlib import Path
import pandas as pd
from concurrent.futures import ThreadPoolExecutor
from tqdm import tqdm
import logging
from datetime import datetime
class ZipScanError(Exception):
"""ZIP 파일 스캔 관련 사용자 정의 예외"""
pass
def find_zip_files(root_path):
"""주어진 경로에서 'original' 폴더 내의 모든 zip 파일을 찾습니다."""
zip_files = []
sizes = []
root = Path(root_path)
for folder_path, _, files in os.walk(root):
if Path(folder_path).name == 'original':
for file in files:
if file.lower().endswith('.zip'):
full_path = Path(folder_path) / file
zip_files.append(str(full_path))
sizes.append(full_path.stat().st_size)
return zip_files, sizes
def save_to_excel(zip_files, sizes, output_path):
"""파일 정보를 엑셀 파일로 저장합니다."""
df = pd.DataFrame({
'파일 경로': zip_files,
'파일명': [Path(f).name for f in zip_files],
'크기(바이트)': sizes,
'크기(MB)': [size / (1024 * 1024) for size in sizes]
})
df.to_excel(output_path, index=False)
print(f"파일이 성공적으로 저장되었습니다: {output_path}")
def main():
try:
# 검색할 루트 경로를 지정합니다
root_path = input("검색할 경로를 입력하세요: ")
# 결과를 저장할 엑셀 파일 경로를 지정합니다
output_path = Path(root_path) / "zip_files_info.xlsx"
# zip 파일들을 찾습니다
zip_files, sizes = find_zip_files_with_progress(root_path)
if not zip_files:
print("ZIP 파일을 찾을 수 없습니다.")
return
# 엑셀 파일로 저장합니다
save_to_excel(zip_files, sizes, output_path)
# 찾은 파일 수를 출력합니다
print(f"총 {len(zip_files)}개의 ZIP 파일을 찾았습니다.")
except Exception as e:
print(f"오류가 발생했습니다: {str(e)}")
if __name__ == "__main__":
main()
마치며
지금까지 Python을 활용하여 ZIP 파일 검색과 관리를 자동화하는 방법을 상세히 살펴보았습니다. 이 코드를 활용하면 수작업으로 몇 시간이 걸리던 작업을 몇 분 안에 처리할 수 있습니다. 특히 대규모 프로젝트나 많은 양의 ZIP 파일을 다루는 환경에서 유용하게 활용될 수 있을 것입니다.