[Python 100일 챌린지] Day 49 - 파일 시스템 고급
Path('downloads').glob('*.jpg')→ 사진 파일만 쏙! 자동 정리! 😊폴더 만들기, 파일 이동, 중복 파일 찾기, 오래된 파일 삭제… Windows 탐색기가 하는 일을 Python으로 자동화합니다!
(45-55분 완독 ⭐⭐⭐)
🎯 오늘의 학습 목표
📚 사전 지식
- Day 48: 디버깅 기법
- Phase 4의 객체지향 프로그래밍 개념
🎯 학습 목표 1: os와 pathlib 모듈 이해하기
1.1 os vs pathlib 비교
💡 어떤 것을 사용해야 할까요? Python 3.4+에서는 pathlib을 권장합니다. 객체 지향적이고, 코드가 더 읽기 쉽습니다. 단, 일부 오래된 라이브러리는 os 모듈만 지원할 수 있습니다.
| 작업 | os 모듈 | pathlib |
|---|---|---|
| 경로 결합 | os.path.join('a', 'b') | Path('a') / 'b' |
| 파일 존재 확인 | os.path.exists('file.txt') | Path('file.txt').exists() |
| 디렉토리 생성 | os.makedirs('dir', exist_ok=True) | Path('dir').mkdir(parents=True, exist_ok=True) |
| 파일 목록 | os.listdir('.') | Path('.').iterdir() |
| 파일명 추출 | os.path.basename('/a/b/c.txt') | Path('/a/b/c.txt').name |
| 확장자 추출 | os.path.splitext('a.txt')[1] | Path('a.txt').suffix |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# os 모듈 방식 (구식)
import os
path = os.path.join('data', 'users.txt')
if os.path.exists(path):
print("파일 존재")
filename = os.path.basename(path) # 'users.txt'
# pathlib 방식 (권장!)
from pathlib import Path
path = Path('data') / 'users.txt'
if path.exists():
print("파일 존재")
filename = path.name # 'users.txt'
1.2 pathlib 기본 사용법
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from pathlib import Path
# 경로 생성
path = Path('data/users.txt')
# 경로 결합 (/ 연산자 사용!)
config_dir = Path('config')
config_file = config_dir / 'settings.json'
print(config_file) # config/settings.json
# 존재 확인
if path.exists():
print("파일 존재")
# 파일인지 디렉토리인지
print(path.is_file()) # True/False
print(path.is_dir()) # True/False
💡 경로 결합에
/연산자를 사용하면 Windows와 Mac/Linux 모두에서 올바르게 동작합니다. 문자열로'data/' + 'file.txt'처럼 직접 결합하면 OS별로 문제가 생길 수 있습니다.
1.3 경로 정보 추출
1
2
3
4
5
6
7
8
9
10
from pathlib import Path
path = Path('/home/user/project/data.txt')
print(path.name) # data.txt (파일명)
print(path.stem) # data (확장자 제외 파일명)
print(path.suffix) # .txt (확장자)
print(path.parent) # /home/user/project (부모 디렉토리)
print(path.parts) # ('/', 'home', 'user', 'project', 'data.txt')
print(path.absolute()) # 절대 경로
출력 결과:
1
2
3
4
5
6
data.txt
data
.txt
/home/user/project
('/', 'home', 'user', 'project', 'data.txt')
/home/user/project/data.txt
1.4 현재 작업 디렉토리
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from pathlib import Path
import os
# pathlib으로 현재 디렉토리
current = Path.cwd()
print(f"현재 디렉토리: {current}")
# 홈 디렉토리
home = Path.home()
print(f"홈 디렉토리: {home}")
# os 모듈로 현재 디렉토리
print(f"현재 디렉토리 (os): {os.getcwd()}")
# 작업 디렉토리 변경 (os 모듈만 가능)
# os.chdir('/some/path')
출력 결과:
1
2
3
현재 디렉토리: /Users/user/project
홈 디렉토리: /Users/user
현재 디렉토리 (os): /Users/user/project
🎯 학습 목표 2: 파일 및 디렉토리 조작하기
2.1 디렉토리 생성
1
2
3
4
5
6
7
8
9
10
from pathlib import Path
# 단일 디렉토리 생성
new_dir = Path('backup')
new_dir.mkdir(exist_ok=True) # 이미 있어도 오류 안 냄
# 중첩 디렉토리 생성 (parents=True)
nested_dir = Path('data/2025/01/logs')
nested_dir.mkdir(parents=True, exist_ok=True)
# parents=True: 중간 디렉토리(data, 2025, 01)도 자동 생성
💡 mkdir() 옵션
parents=True: 중간 디렉토리가 없으면 함께 생성exist_ok=True: 이미 디렉토리가 있어도 오류 발생하지 않음- 둘 다 False(기본값)면 오류 발생 가능!
2.2 파일 및 디렉토리 삭제
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from pathlib import Path
import shutil
# 파일 삭제
file = Path('temp.txt')
if file.exists():
file.unlink() # 파일 삭제
print("파일 삭제됨")
# 빈 디렉토리 삭제
empty_dir = Path('empty_folder')
if empty_dir.exists() and empty_dir.is_dir():
empty_dir.rmdir() # 빈 디렉토리만 삭제 가능!
# 파일이 있는 디렉토리 삭제 (shutil 사용)
dir_with_files = Path('data/backup')
if dir_with_files.exists():
shutil.rmtree(dir_with_files) # 내용물 포함 모두 삭제!
print("디렉토리와 모든 내용 삭제됨")
⚠️ 주의:
shutil.rmtree()는 디렉토리와 모든 내용을 영구 삭제합니다! 휴지통으로 가지 않으니 신중하게 사용하세요.
2.3 파일 복사/이동/이름 변경
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from pathlib import Path
import shutil
# 파일 복사
shutil.copy('original.txt', 'copy.txt')
print("파일 복사 완료")
# 파일 이동
shutil.move('old_location/file.txt', 'new_location/file.txt')
print("파일 이동 완료")
# 파일 이름 변경 (pathlib)
file = Path('old_name.txt')
file.rename('new_name.txt')
# 디렉토리 전체 복사
shutil.copytree('source_folder', 'backup_folder')
print("디렉토리 복사 완료")
2.4 디렉토리 순회
1
2
3
4
5
6
7
8
9
from pathlib import Path
# 현재 디렉토리의 모든 파일과 폴더 (1단계만)
print("=== 현재 디렉토리 내용 ===")
for item in Path('.').iterdir():
if item.is_dir():
print(f"📁 {item.name}/")
else:
print(f"📄 {item.name}")
출력 예시:
1
2
3
4
5
6
=== 현재 디렉토리 내용 ===
📁 data/
📁 src/
📄 main.py
📄 config.json
📄 README.md
2.5 파일 검색 (glob)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from pathlib import Path
# 현재 디렉토리의 .py 파일만 (1단계)
print("=== Python 파일 ===")
for py_file in Path('.').glob('*.py'):
print(py_file)
# 모든 하위 디렉토리 포함 검색 (재귀적)
print("\n=== 모든 Python 파일 (하위 폴더 포함) ===")
for py_file in Path('.').rglob('*.py'):
print(py_file)
# 여러 패턴 검색
print("\n=== 설정 파일들 ===")
for pattern in ['*.json', '*.yaml', '*.yml', '*.ini']:
for file in Path('.').glob(pattern):
print(file)
출력 예시:
1
2
3
4
5
6
7
8
9
10
=== Python 파일 ===
main.py
utils.py
=== 모든 Python 파일 (하위 폴더 포함) ===
main.py
utils.py
src/app.py
src/models/user.py
tests/test_main.py
💡 glob vs rglob
glob('*.py'): 현재 디렉토리만 검색rglob('*.py'): 모든 하위 디렉토리까지 재귀적(recursive) 검색
2.6 고급 파일 필터링
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from pathlib import Path
def find_large_files(directory, min_size_mb=10):
"""지정 크기 이상의 큰 파일 찾기"""
min_bytes = min_size_mb * 1024 * 1024
large_files = []
for file in Path(directory).rglob('*'):
if file.is_file():
size = file.stat().st_size
if size > min_bytes:
size_mb = size / 1024 / 1024
large_files.append((file, size_mb))
# 크기순 정렬 (큰 파일이 먼저)
large_files.sort(key=lambda x: x[1], reverse=True)
return large_files
# 사용 예시
print("=== 5MB 이상 파일 ===")
for file, size in find_large_files('.', min_size_mb=5):
print(f"{file}: {size:.2f}MB")
출력 예시:
1
2
3
4
=== 5MB 이상 파일 ===
data/videos/intro.mp4: 125.50MB
data/images/photo.png: 15.30MB
logs/debug.log: 8.25MB
🎯 학습 목표 3: 파일 정보 확인하기
3.1 파일 메타데이터
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from pathlib import Path
from datetime import datetime
file = Path('data.txt')
if file.exists():
stat = file.stat()
# 파일 크기
size_bytes = stat.st_size
size_kb = size_bytes / 1024
size_mb = size_kb / 1024
print(f"크기: {size_bytes} bytes ({size_kb:.2f} KB)")
# 수정 시간 (마지막으로 내용이 변경된 시간)
mtime = datetime.fromtimestamp(stat.st_mtime)
print(f"수정 시간: {mtime}")
# 생성 시간 (Windows) / 메타데이터 변경 시간 (Unix)
ctime = datetime.fromtimestamp(stat.st_ctime)
print(f"생성/변경 시간: {ctime}")
# 마지막 접근 시간
atime = datetime.fromtimestamp(stat.st_atime)
print(f"접근 시간: {atime}")
출력 예시:
1
2
3
4
크기: 15360 bytes (15.00 KB)
수정 시간: 2025-04-18 10:30:45
생성/변경 시간: 2025-04-17 09:15:22
접근 시간: 2025-04-18 14:20:10
3.2 파일 권한 확인
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from pathlib import Path
import os
file = Path('data.txt')
# os.access()로 권한 확인
if os.access(file, os.R_OK):
print("✅ 읽기 가능")
else:
print("❌ 읽기 불가")
if os.access(file, os.W_OK):
print("✅ 쓰기 가능")
else:
print("❌ 쓰기 불가")
if os.access(file, os.X_OK):
print("✅ 실행 가능")
else:
print("❌ 실행 불가")
3.3 파일 정보 요약 함수
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
from pathlib import Path
from datetime import datetime
def file_info(file_path):
"""파일 정보 요약 출력"""
path = Path(file_path)
if not path.exists():
print(f"❌ 파일이 존재하지 않습니다: {file_path}")
return
stat = path.stat()
size = stat.st_size
mtime = datetime.fromtimestamp(stat.st_mtime)
# 크기 단위 변환
if size < 1024:
size_str = f"{size} B"
elif size < 1024 * 1024:
size_str = f"{size / 1024:.2f} KB"
else:
size_str = f"{size / 1024 / 1024:.2f} MB"
print(f"📄 파일: {path.name}")
print(f" 경로: {path.absolute()}")
print(f" 크기: {size_str}")
print(f" 확장자: {path.suffix}")
print(f" 수정일: {mtime.strftime('%Y-%m-%d %H:%M:%S')}")
# 사용
file_info('main.py')
출력 예시:
1
2
3
4
5
📄 파일: main.py
경로: /Users/user/project/main.py
크기: 2.35 KB
확장자: .py
수정일: 2025-04-18 10:30:45
3.4 오래된 파일 찾기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from pathlib import Path
from datetime import datetime, timedelta
def find_old_files(directory, days=30):
"""지정 일수보다 오래된 파일 찾기"""
cutoff = datetime.now() - timedelta(days=days)
old_files = []
for file in Path(directory).rglob('*'):
if file.is_file():
mtime = datetime.fromtimestamp(file.stat().st_mtime)
if mtime < cutoff:
old_files.append((file, mtime))
# 오래된 순으로 정렬
old_files.sort(key=lambda x: x[1])
return old_files
# 30일 이상 지난 파일 찾기
print("=== 30일 이상 오래된 파일 ===")
for file, mtime in find_old_files('.', days=30):
print(f"{file}: {mtime.strftime('%Y-%m-%d')}")
🎯 학습 목표 4: 경로 처리 베스트 프랙티스 익히기
4.1 임시 파일과 디렉토리
💡 임시 파일이 필요한 경우: 다운로드 중간 파일, 변환 작업 중 임시 저장, 테스트용 파일 등. 프로그램 종료 시 자동으로 삭제됩니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import tempfile
from pathlib import Path
# 임시 파일 생성
with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False) as f:
f.write("임시 데이터입니다.")
temp_path = f.name
print(f"임시 파일 생성: {temp_path}")
# 임시 파일 사용 후 삭제
Path(temp_path).unlink()
print("임시 파일 삭제 완료")
# 임시 디렉토리 (with 블록 벗어나면 자동 삭제)
with tempfile.TemporaryDirectory() as temp_dir:
print(f"임시 디렉토리: {temp_dir}")
# 임시 디렉토리 안에 파일 생성
temp_file = Path(temp_dir) / 'data.txt'
temp_file.write_text("임시 데이터")
print(f"임시 파일: {temp_file}")
# with 블록 벗어나면 디렉토리와 내용물 모두 자동 삭제!
print("임시 디렉토리 자동 삭제됨")
출력 예시:
1
2
3
4
5
임시 파일 생성: /tmp/tmp3x8k2f9a.txt
임시 파일 삭제 완료
임시 디렉토리: /tmp/tmpg7h4r2lm
임시 파일: /tmp/tmpg7h4r2lm/data.txt
임시 디렉토리 자동 삭제됨
4.2 크로스 플랫폼 경로 처리
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from pathlib import Path
# ✅ 좋은 예: pathlib 사용 (자동으로 OS에 맞게 처리)
data_dir = Path('data')
config_file = data_dir / 'settings' / 'config.json'
print(config_file) # Windows: data\settings\config.json
# Mac/Linux: data/settings/config.json
# ❌ 나쁜 예: 문자열로 직접 경로 결합
# bad_path = 'data' + '/' + 'settings' + '/' + 'config.json'
# Windows에서는 '\' 사용하므로 문제 발생!
# 절대 경로로 변환
abs_path = config_file.resolve()
print(f"절대 경로: {abs_path}")
# 상대 경로 계산
base = Path('/home/user/project')
target = Path('/home/user/project/src/main.py')
# relative_to()로 상대 경로 구하기
try:
rel_path = target.relative_to(base)
print(f"상대 경로: {rel_path}") # src/main.py
except ValueError:
print("상대 경로를 계산할 수 없습니다")
4.3 안전한 파일 작업 패턴
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
from pathlib import Path
import shutil
def safe_delete(path):
"""안전한 파일/디렉토리 삭제"""
p = Path(path)
if not p.exists():
print(f"⚠️ 존재하지 않음: {path}")
return False
if p.is_file():
p.unlink()
print(f"✅ 파일 삭제: {path}")
elif p.is_dir():
shutil.rmtree(p)
print(f"✅ 디렉토리 삭제: {path}")
return True
def safe_copy(src, dst):
"""안전한 파일 복사 (덮어쓰기 확인)"""
src_path = Path(src)
dst_path = Path(dst)
if not src_path.exists():
print(f"❌ 원본 파일 없음: {src}")
return False
if dst_path.exists():
print(f"⚠️ 대상 파일 이미 존재: {dst}")
# 실제로는 사용자 확인 필요
return False
# 대상 디렉토리가 없으면 생성
dst_path.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(src, dst) # copy2는 메타데이터도 복사
print(f"✅ 복사 완료: {src} → {dst}")
return True
# 사용
safe_copy('original.txt', 'backup/original.txt')
4.4 파일 읽기/쓰기 (pathlib)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from pathlib import Path
# pathlib으로 간단하게 파일 읽기/쓰기
file = Path('example.txt')
# 텍스트 쓰기
file.write_text("Hello, World!\n안녕하세요!", encoding='utf-8')
print("파일 쓰기 완료")
# 텍스트 읽기
content = file.read_text(encoding='utf-8')
print(f"파일 내용:\n{content}")
# 바이너리 읽기/쓰기
binary_file = Path('data.bin')
binary_file.write_bytes(b'\x00\x01\x02\x03')
data = binary_file.read_bytes()
print(f"바이너리 데이터: {data}")
🎯 학습 목표 5: 실전 프로젝트 - 파일 자동 정리기
5.1 다운로드 폴더 자동 정리기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
from pathlib import Path
import shutil
from datetime import datetime
# 확장자별 카테고리 정의
FILE_CATEGORIES = {
'images': ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.svg', '.webp'],
'documents': ['.pdf', '.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx', '.txt'],
'videos': ['.mp4', '.avi', '.mkv', '.mov', '.wmv'],
'audio': ['.mp3', '.wav', '.flac', '.aac', '.m4a'],
'archives': ['.zip', '.rar', '.7z', '.tar', '.gz'],
'code': ['.py', '.js', '.html', '.css', '.json', '.xml'],
}
def get_category(file_path):
"""파일 확장자로 카테고리 결정"""
suffix = file_path.suffix.lower()
for category, extensions in FILE_CATEGORIES.items():
if suffix in extensions:
return category
return 'others'
def organize_downloads(source_dir):
"""다운로드 폴더 정리"""
source = Path(source_dir)
if not source.exists():
print(f"❌ 디렉토리가 존재하지 않습니다: {source}")
return
moved_count = 0
for file in source.iterdir():
if file.is_file():
# 카테고리 결정
category = get_category(file)
# 카테고리 폴더 생성
category_dir = source / category
category_dir.mkdir(exist_ok=True)
# 파일 이동
dest = category_dir / file.name
# 같은 이름의 파일이 있으면 이름 변경
if dest.exists():
stem = file.stem
suffix = file.suffix
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
dest = category_dir / f"{stem}_{timestamp}{suffix}"
shutil.move(str(file), str(dest))
print(f"✅ {file.name} → {category}/")
moved_count += 1
print(f"\n총 {moved_count}개 파일 정리 완료!")
# 사용 예시
# organize_downloads('~/Downloads')
5.2 중복 파일 찾기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
from pathlib import Path
import hashlib
def get_file_hash(file_path):
"""파일의 MD5 해시 계산"""
hash_md5 = hashlib.md5()
with open(file_path, 'rb') as f:
for chunk in iter(lambda: f.read(4096), b''):
hash_md5.update(chunk)
return hash_md5.hexdigest()
def find_duplicates(directory):
"""중복 파일 찾기"""
hash_dict = {} # {해시: [파일 경로들]}
duplicates = []
print(f"디렉토리 검색 중: {directory}")
for file in Path(directory).rglob('*'):
if file.is_file():
try:
file_hash = get_file_hash(file)
if file_hash in hash_dict:
hash_dict[file_hash].append(file)
else:
hash_dict[file_hash] = [file]
except Exception as e:
print(f"⚠️ 오류 ({file}): {e}")
# 중복 파일 추출
for file_hash, files in hash_dict.items():
if len(files) > 1:
duplicates.append(files)
return duplicates
# 사용 예시
print("=== 중복 파일 찾기 ===")
duplicate_groups = find_duplicates('.')
for i, group in enumerate(duplicate_groups, 1):
print(f"\n중복 그룹 {i}:")
for file in group:
size_kb = file.stat().st_size / 1024
print(f" - {file} ({size_kb:.1f} KB)")
💡 실전 팁 & 주의사항
✅ 파일 시스템 베스트 프랙티스
- 항상 pathlib 사용
1 2 3 4 5 6
# ✅ 좋은 예 from pathlib import Path path = Path('data') / 'file.txt' # ❌ 나쁜 예 (OS별로 다르게 동작) path = 'data/' + 'file.txt'
- 존재 확인 후 작업
1 2 3
path = Path('data') if not path.exists(): path.mkdir(parents=True, exist_ok=True)
- 삭제 전 확인 습관화
1 2 3 4 5
# 삭제 전 내용 확인 for item in path.iterdir(): print(item) # 확인 후 삭제 # shutil.rmtree(path)
- 예외 처리 필수
1 2 3 4 5 6
try: shutil.copy(src, dst) except PermissionError: print("권한이 없습니다") except FileNotFoundError: print("파일을 찾을 수 없습니다")
⚠️ 주의사항
| 위험 행위 | 결과 | 안전한 방법 |
|---|---|---|
shutil.rmtree() | 복구 불가 삭제 | 먼저 내용 확인 |
| 상대 경로 사용 | 예상과 다른 위치 | path.resolve() 확인 |
| 권한 무시 | PermissionError | os.access() 확인 |
| 인코딩 미지정 | UnicodeDecodeError | encoding='utf-8' 명시 |
🧪 연습 문제
문제 1: 파일 정리 도구
목표: 특정 확장자 파일을 자동으로 폴더별로 정리하는 함수를 작성하세요.
요구사항:
- 확장자별로 폴더 생성 (예: txt, py, json)
- 파일을 해당 폴더로 이동
- 이동한 파일 수 출력
해답 보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from pathlib import Path
import shutil
def organize_files(source_dir):
"""파일 정리 (확장자별 폴더 생성)"""
source = Path(source_dir)
moved_count = 0
for file in source.iterdir():
if file.is_file():
# 확장자 추출 (점 제거)
ext = file.suffix[1:] if file.suffix else 'no_extension'
# 확장자 폴더 생성
ext_dir = source / ext
ext_dir.mkdir(exist_ok=True)
# 파일 이동
dest = ext_dir / file.name
shutil.move(str(file), str(dest))
print(f"이동: {file.name} → {ext}/")
moved_count += 1
print(f"\n총 {moved_count}개 파일 정리 완료!")
return moved_count
# 테스트
# organize_files('downloads')
문제 2: 디렉토리 용량 분석기
목표: 디렉토리의 총 용량과 파일 개수를 계산하는 함수를 작성하세요.
요구사항:
- 하위 디렉토리 포함 전체 용량 계산
- 파일 개수와 디렉토리 개수 각각 출력
- 용량은 KB, MB, GB 단위로 표시
해답 보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
from pathlib import Path
def format_size(bytes_size):
"""바이트를 읽기 쉬운 단위로 변환"""
if bytes_size < 1024:
return f"{bytes_size} B"
elif bytes_size < 1024 * 1024:
return f"{bytes_size / 1024:.2f} KB"
elif bytes_size < 1024 * 1024 * 1024:
return f"{bytes_size / 1024 / 1024:.2f} MB"
else:
return f"{bytes_size / 1024 / 1024 / 1024:.2f} GB"
def analyze_directory(directory):
"""디렉토리 용량 분석"""
path = Path(directory)
if not path.exists():
print(f"❌ 디렉토리가 존재하지 않습니다: {directory}")
return
total_size = 0
file_count = 0
dir_count = 0
for item in path.rglob('*'):
if item.is_file():
total_size += item.stat().st_size
file_count += 1
elif item.is_dir():
dir_count += 1
print(f"📁 디렉토리: {path.absolute()}")
print(f" 총 용량: {format_size(total_size)}")
print(f" 파일 수: {file_count}개")
print(f" 폴더 수: {dir_count}개")
return {
'total_size': total_size,
'file_count': file_count,
'dir_count': dir_count
}
# 테스트
analyze_directory('.')
출력 예시:
1
2
3
4
📁 디렉토리: /Users/user/project
총 용량: 125.50 MB
파일 수: 234개
폴더 수: 45개
📝 오늘 배운 내용 정리
| 개념 | 설명 | 예시 |
|---|---|---|
| Path | 경로 객체 | Path('data/file.txt') |
| 경로 결합 | / 연산자 사용 | Path('data') / 'file.txt' |
| mkdir | 디렉토리 생성 | path.mkdir(parents=True, exist_ok=True) |
| glob | 패턴 매칭 | Path('.').glob('*.py') |
| rglob | 재귀 검색 | Path('.').rglob('*.txt') |
| stat | 파일 정보 | path.stat().st_size |
| shutil | 파일 복사/이동 | shutil.copy(src, dst) |
| tempfile | 임시 파일 | tempfile.TemporaryDirectory() |
| unlink | 파일 삭제 | path.unlink() |
| rmtree | 디렉토리 삭제 | shutil.rmtree(path) |
핵심 코드 패턴
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
from pathlib import Path
import shutil
# 경로 객체 생성
path = Path('data') / 'users' / 'info.txt'
# 디렉토리 생성
Path('data/backup').mkdir(parents=True, exist_ok=True)
# 파일 검색 (현재 디렉토리)
for file in Path('.').glob('*.py'):
print(file)
# 파일 검색 (하위 디렉토리 포함)
for file in Path('.').rglob('*.py'):
print(file)
# 파일 정보
file = Path('data.txt')
if file.exists():
size = file.stat().st_size
mtime = file.stat().st_mtime
print(f"크기: {size}, 수정시간: {mtime}")
# 파일 읽기/쓰기 (pathlib)
file.write_text("Hello, World!", encoding='utf-8')
content = file.read_text(encoding='utf-8')
# 파일 복사/이동/삭제
shutil.copy('source.txt', 'dest.txt')
shutil.move('old.txt', 'new.txt')
Path('temp.txt').unlink() # 파일 삭제
🔗 관련 자료
📚 이전 학습
Day 48: 디버깅 기법 ⭐⭐⭐
어제는 print 디버깅과 pdb 디버거로 버그를 효율적으로 찾고 수정하는 방법을 배웠습니다!
📚 다음 학습
Day 50: 미니 프로젝트 - 로그 분석기 ⭐⭐⭐⭐
내일은 Phase 5의 마지막 날! 지금까지 배운 모든 내용을 활용해 실전 로그 분석기를 만듭니다!
“늦었다고 생각할 때가 가장 빠른 시기입니다!” 🚀
Day 49/100 Phase 5: 파일 처리와 예외 처리 #100DaysOfPython
이제와서 시작하는 Python 마스터하기 - Day 49 완료! 🎉
