포스트

[Python 100일 챌린지] Day 49 - 파일 시스템 고급

[Python 100일 챌린지] Day 49 - 파일 시스템 고급

Path('downloads').glob('*.jpg') → 사진 파일만 쏙! 자동 정리! 😊

폴더 만들기, 파일 이동, 중복 파일 찾기, 오래된 파일 삭제… Windows 탐색기가 하는 일을 Python으로 자동화합니다!

(45-55분 완독 ⭐⭐⭐)

🎯 오늘의 학습 목표

📚 사전 지식


🎯 학습 목표 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)")

💡 실전 팁 & 주의사항

✅ 파일 시스템 베스트 프랙티스

  1. 항상 pathlib 사용
    1
    2
    3
    4
    5
    6
    
    # ✅ 좋은 예
    from pathlib import Path
    path = Path('data') / 'file.txt'
    
    # ❌ 나쁜 예 (OS별로 다르게 동작)
    path = 'data/' + 'file.txt'
    
  2. 존재 확인 후 작업
    1
    2
    3
    
    path = Path('data')
    if not path.exists():
        path.mkdir(parents=True, exist_ok=True)
    
  3. 삭제 전 확인 습관화
    1
    2
    3
    4
    5
    
    # 삭제 전 내용 확인
    for item in path.iterdir():
        print(item)
    # 확인 후 삭제
    # shutil.rmtree(path)
    
  4. 예외 처리 필수
    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 완료! 🎉

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.