os.walk() 是最稳妥的目录遍历方式,自动深度优先遍历并返回 root、dirs、files;需在内层循环用 try/except 处理 PermissionError 等异常,避免中断统计。

用 os.walk() 遍历统计最稳妥
直接递归调用 os.listdir() 或手动拼路径容易漏掉嵌套深层目录,也难处理权限错误。而 os.walk() 是 Python 标准库中专为这种需求设计的工具,它自动按深度优先遍历子目录,返回每层的 root、dirs、files 三元组,可控且健壮。
实操建议:
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
立即学习“Python免费学习笔记(深入)”;
- 对每个
file调用os.path.getsize(),累加时用try/except OSError捕获权限不足或文件被占用等异常,避免整个统计中断 - 不要在循环里反复调用
os.path.join(root, f)拼路径再判断是否是文件——os.walk()返回的files列表里全是当前root下的纯文件名,直接拼一次即可 - 如果路径含中文或特殊字符,确保 Python 运行环境编码一致(通常默认 UTF-8,一般无需额外处理)
pathlib 写法更简洁但要注意符号链接
Python 3.4+ 的 pathlib 提供面向对象风格,Path.rglob("*") 可以一行展开所有子孙节点,配合 .is_file() 和 .stat().st_size 很直观。但它默认会跟随符号链接(symlink),若目标指向的是另一个大目录,可能重复计算或进入无限循环。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 用
Path.rglob("*")后必须加if p.is_file() and not p.is_symlink()双重过滤 - 避免用
Path.glob("**/*"),它不保证跨平台行为一致(某些系统 shell 层会展开通配符) - 对大目录,
pathlib方式内存占用略高,因为会先生成全部Path对象再逐个检查;os.walk()是迭代器,更省内存
遇到 PermissionError 别让它崩掉
Windows 上访问 System Volume Information,Linux/macOS 上遇到 root 权限目录,都会抛出 PermissionError。默认未捕获时程序直接退出,但实际你只想要“尽力而为”的总大小。
关键处理点:
- 在
os.walk()外层不捕获异常,在遍历内部对每个root做try/except,这样即使某个子目录进不去,后续兄弟目录仍可继续统计 - 不要用
os.walk(top, onerror=...)的回调方式——它只能告诉你哪一层出错,无法跳过并继续向下走;正确做法是在内层循环前对root尝试os.listdir()并捕获异常 - 日志可选:把报错路径写入
stderr或简单 print,方便事后排查,但别让它们阻塞主流程
注意硬链接和稀疏文件的实际字节数
os.path.getsize() 和 Path.stat().st_size 返回的是文件的逻辑大小(即你看到的“文件大小”),不是磁盘占用。这对绝大多数场景是对的,但有两个例外:
- 硬链接(hard link):多个路径指向同一 inode,
st_size会被重复计入多次——如果你要算“磁盘真实占用”,得用st_ino+st_dev去 dedupe,但一般不需要 - 稀疏文件(sparse file):比如数据库快照、虚拟机镜像,
st_size很大但实际只占少量磁盘块——此时应看st_blocks * 512(POSIX),但 Windows 不支持该字段,跨平台时保持用st_size更一致
除非你在做存储审计或备份校验,否则直接用 st_size 就是用户真正关心的“文件夹里所有文件加起来有多大”。

















