TIL/Python

[TIL] pathlib 로 디렉토리 내 파일 총합 구하기 w/ Python

아람2 2025. 7. 9. 19:25
반응형

Python 의 pathlib 모듈을 활용해 디렉토리 내 파일 목록을 탐색하고

각 파일의 크기를 계산해 총 용량을 구하는 프로그램을 작성해봤다 

pathlib 내의 Path 클래스는 파일이나 폴더 경로를 객체처럼 다룰 수 있게 해줘서,

문자열보다 훨씬 편리하게 경로 조작을 할 수 있다 

작업 디렉토리 설정 및 출력 폴더 생성

from pathlib import Path

__file__  # 현재 실행 중인 파일 경로
WORK_DIR = Path(__file__).parent
OUT_DIR = WORK_DIR / "output"
OUT_DIR.mkdir(exist_ok=True)

__file__ 은 현재 실행 중인 Python File 의 전체 경로를 담고 있는 내장 변수이다 

Path(__file__) 로 __file__ 문자열을 Path 객체로 변환하고, 

.parent 는 그 파일이 속한 디렉토리 경로를 의미한다 

이를 통해 현재 실행 중인 파일의 경로를 WORK_DIR 변수에 저장한다 

WORK_DIR / "output" 로 WORK_DIR 경로 안에 "output" 하위 폴더 경로를 만들어주고, mkdir() 로 폴더를 만든다

🐣 헷갈릴 수 있는데 / 는 <경로> 를 합치는 연산이고, mkdir() 로 진짜 폴더를 만드는 동작이다 🐣

exist_ok 옵션은 해당 폴더가 이미 존재한다면 에러 없이 그냥 넘어가고, 없다면 새로 만들라는 의미이다 

디렉토리 내 파일/ 폴더 목록 추출

# 파일 목록 추출 (폴더 포함)
for path in WORK_DIR.iterdir():
    print(path)

# 파일 목록 추출 (폴더만)
for path in WORK_DIR.iterdir():
    if path.is_dir():
        print(path)

# 파일 목록 추출 (파일만)
for path in WORK_DIR.glob("*"):
    if path.is_file():
        print(path)

 

iterdir() 은 해당 디렉토리의 모든 항목 (파일 + 폴더) 을 하나씩 순회할 수 있게 해주는 메서드이다
이를 for 문과 함께 사용하면 디렉토리 안의 모든 경로(파일, 폴더 포함)를 출력할 수 있다 

is_dir() 메서드를 통해 폴더인지 아닌지를 판별할 수 있고, 이를 조건으로 걸면 폴더만 출력할 수 있다

glob("*") 는 지정된 패턴에 해당하는 항목을 순회할 수 있게 해주는 메서드다
여기서는 "*" 패턴을 사용했기 때문에 현재 디렉토리의 모든 파일과 폴더가 대상이 되고,
그 중 is_file() 조건으로 파일만 출력할 수 있다

🐣 * 는 Asterisk, 모든 항목을 의미하는 와일드카드이다 🐣

파일 크기 출력 및 합계 계산

total_size = 0
for path in WORK_DIR.glob("*"):
    if path.is_file():
        print(f"{path.name} {path.stat().st_size}")
        total_size += path.stat().st_size

print(f"{total_size=}")

path.stat() 은 해당 파일의 메타데이터 (상세 정보) 를 담은 객체를 반환한다 
여기에는 파일 크기, 생성 시간, 수정 시간 등 다양한 정보가 들어 있고, 출력 결과는 아래와 같다  

os.stat_result(st_mode=33188, st_ino=22641789, st_dev=16777234, st_nlink=1, st_uid=501, st_gid=20, st_size=822, st_atime=1752037464, st_mtime=1752037463, st_ctime=1752037463)
os.stat_result(st_mode=33188, st_ino=22641788, st_dev=16777234, st_nlink=1, st_uid=501, st_gid=20, st_size=833, st_atime=1752037464, st_mtime=1752037463, st_ctime=1752037463)

stat().st_size는 그 중에서도 파일의 크기 (Byte 단위) 를 의미한다

이 코드는 현재 디렉토리에 있는 파일들을 순회하면서 각 파일의 이름과 크기를 하나씩 출력하고,

total_size 변수에 누적해서 디렉토리 내 파일들의 총 용량을 계산한 뒤,

마지막에 최종 합계를 f-string 으로 출력해준다

총 파일 크기 계산 

def get_total_filesize(base_dir: Path, pattern: str = "*"):
    total_size = 0
    for path in base_dir.glob(pattern):
        if path.is_file():
            total_size += path.stat().st_size
    return total_size
    
get_total_filesize(WORK_DIR)

앞에서 했던 디렉토리 내 파일 크기 계산 코드를 함수로 정리한 버전이다 
지정한 디렉토리를 순회하면서 파일 크기를 누적하고, 최종 합계를 반환한다 

base_dir 에는 탐색할 기준이 되는 폴더 경로 (Path 객체) 를 넘겨주고,
pattern 에는 어떤 glob 패턴으로 탐색할지를 지정할 수 있다 
기본값은 "*" 이므로 현재 디렉토리 안의 모든 파일이 대상이다 

🐣 Type Hine

여기서 base_dir: Path, pattern: str 처럼 : 뒤에 타입을 적는 문법은

함수의 인자와 반환값의 자료형을 명시하는 Type Hint, 타입 힌트 이다

함수의 반환값을 명시하고 싶은 경우에는 아래와 같이 사용할 수 있다 ( -> int 부분 )

get_total_filesize(base_dir: Path, pattern: str = "*") -> int

이 함수는 Path 와 str 타입의 인자를 받고, int 타입 (정수) 을 반환한다는 의미이다 

Type Hint 의 의미는 다음과 같다 

인자 이름 타입 힌트  의미 
base_dir Path base_dir 는 pathlib.Path 타입이어야 한다 
pattern str pattern 인자는 문자열이어야 하며, glob 패턴으로 사용된다 
-> int 반환값  이 함수는 int 타입 (정수) 를 반환한다 

 

홈 디렉토리 하위 폴더 목록 JSON 저장 

import json

OUT_1 = OUT_DIR / "out_1.json"

def dump_dirnames(base_dir: Path):
    dirs = []
    for path in base_dir.glob("*"):
        if path.is_dir():
            dirs.append(path.as_posix())
    dirs_sorted = sorted(dirs)

    with open(OUT_1, "w", encoding="utf-8") as fp:
        json.dump(dirs_sorted, fp, indent=2, ensure_ascii=False)

dump_dirnames(Path.home())

 

dump_dirnames 함수는 base_dir.glob("*")으로 그 폴더 안 모든 항목을 탐색하고 폴더만 리스트에 담는다

리스트에 담은 폴더 경로들은 as_posix() 을 사용해 문자열 경로로 바꾸고 

sorted() 로 정렬한 폴더 리스트를 json.dump() 를 사용하여 out_1.json 파일로 저장한다 

indent=2 옵션은 안 써도 되지만, 보기 좋게 2칸 들여쓰기를 하는 옵션이고, 

ensure_ascii 를 False 로 지정하여 한글이 한글로 출력되도록 한다 

(기본값 True 나 명시하지 않은 경우 한글이 유니코드 이스케이프 형태로 출력된다) 

그리고 나서 dump_dirnames(Path.home())를 호출해 사용자 홈 폴더 안의 하위 폴더 목록을 JSON 으로 저장한다

폴더별 총 파일 크기 JSON 으로 저장

OUT_2 = OUT_DIR / "out_2.json"

def dump_filesize_from_dirnames():
    with open(OUT_1, encoding="utf-8") as fp:
        target = json.load(fp)

    result = {}
    for path_str in target:
        result[path_str] = get_total_filesize(Path(path_str), "**/*")

    with open(OUT_2, "w", encoding="utf-8") as fp:
        json.dump(result, fp, indent=2, ensure_ascii=False)

dump_filesize_from_dirnames()

이 함수는 앞에서 저장한 out_1.json 파일을 열어서 폴더 목록을 읽어온다

각 폴더의 전체 파일 크기를 계산하는데 "**/*" 패턴을 사용해서 하위 폴더까지 포함시킨다  

계산한 폴더 경로별 파일 크기는 딕셔너리에 저장하고, 이 딕셔너리를 out_2.json 파일로 저장한다 

out_2.json 예시 출력 

{'/Users/ahram/Desktop': 47331912584,
 '/Users/ahram/Documents': 2729658,
 '/Users/ahram/Downloads': 6441534859}

 


 

open(file, mode='r', encoding='utf-8') 이런 거 쓰다가 pathlib 로 경로랑 파일을 객체로 다루니까 훨씬 편하다 

    with open(OUTPUT, "w", encoding="utf-8") as fp:
        json.dump(result, fp, indent=2, ensure_ascii=False)

 

이거 메모장에 추가해놔야지~~

 

 

반응형