os.stat() 이 파일 하나의 메타데이터를 돌려준다. 권한 문자열은 stat.filemode() 로 사람이 읽는 형태로 바꾼다.
import os
import stat
import time
path = "sample.txt"
st = os.stat(path)
print(f"{stat.filemode(st.st_mode)} {st.st_nlink} {st.st_uid} {st.st_gid} "
f"{st.st_size} {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(st.st_mtime))} {path}")
| 속성 | 뜻 |
|---|---|
st_size |
바이트 크기 |
st_mode |
파일 종류와 권한 비트 |
st_uid · st_gid |
소유자 · 그룹 ID (숫자) |
st_mtime |
내용이 마지막으로 바뀐 시각 |
st_atime |
마지막 접근 시각 |
st_ctime |
리눅스에서는 생성 시각이 아니라 inode 메타데이터가 바뀐 시각 |
st_ctime 을 생성 시각으로 쓰면 안 된다. 리눅스에서 생성 시각은 파일시스템이 지원할 때만 os.stat(path).st_birthtime(Python 3.12 이상, 지원 플랫폼) 이나 statx 로 얻을 수 있다.
숫자 UID 를 이름으로 바꾸려면 pwd · grp 모듈을 쓴다. 두 모듈은 POSIX 전용이라 Windows 에는 없다.
import pwd, grp
print(pwd.getpwuid(st.st_uid).pw_name, grp.getgrgid(st.st_gid).gr_name)
from pathlib import Path
from datetime import datetime
p = Path("sample.txt")
if p.exists():
st = p.stat()
print(p.name, p.suffix, st.st_size, datetime.fromtimestamp(st.st_mtime))
exists() 로 먼저 확인한 뒤 stat() 을 부르는 방식은 그 사이에 파일이 사라지면 여전히 예외가 난다. 단일 프로세스의 간단한 도구가 아니라면 예외를 잡는 쪽이 정확하다.
try:
st = p.stat()
except FileNotFoundError:
st = None
심볼릭 링크 자체의 정보가 필요하면 os.lstat() 또는 Path.lstat() 을 쓴다. stat() 은 링크를 따라간다.
import os
from pathlib import Path
os.getcwd() # 현재 작업 디렉터리
Path.cwd() # 같은 것, pathlib 형태
Path("sample.txt").resolve() # 절대 경로. 심볼릭 링크도 푼다
os.path.abspath("sample.txt")
스크립트 파일 자신의 위치는 작업 디렉터리와 다르다. 스크립트 옆의 자원을 읽을 때는 __file__ 을 기준으로 잡는다.
BASE_DIR = Path(__file__).resolve().parent
config_path = BASE_DIR / "config.yaml"
디렉터리 목록을 훑을 때는 os.scandir() 이나 Path.iterdir() 이 빠르다. os.scandir() 이 돌려주는 항목은 이미 메타데이터를 들고 있어 항목마다 stat() 을 다시 부르지 않는다.
with os.scandir(".") as it:
for entry in it:
print(entry.name, entry.is_dir(), entry.stat().st_size)