PHP如何获取文件夹大小_PHP计算文件夹总大小【教程】

2次阅读

recursivedirectoryiterator 比 scandir 更可靠,能正确处理符号链接、权限错误、循环软链及跨文件系统边界;需 try/catch 捕获 unexpectedvalueexception,仅对 isfile() 为 true 的项调用 getsize(),避免 filesize() 对目录返回 false 导致计算错误。

PHP如何获取文件夹大小_PHP计算文件夹总大小【教程】

recursiveDirectoryIterator 遍历比 scandir 更可靠

直接递归读取子目录时,scandir 容易漏掉符号链接、权限不足的子目录,或在遇到循环软链时卡死。recursiveDirectoryIterator 内置跳过 ...,还能配合 RecursiveIteratorIterator 控制遍历深度,更贴近真实文件系统行为。

  • 必须用 try/catch 包裹迭代过程,否则权限错误(如 Permission denied)会直接抛出 UnexpectedValueException
  • 避免用 is_dir() + scandir() 手动递归——它不处理挂载点跨文件系统边界,也难控制并发深度
  • 若需排除特定路径(如 node_modules),在迭代中检查 $file->getRealPath()字符串匹配更安全

filesize() 对目录返回 false,别直接累加

phpfilesize() 对目录始终返回 false(不是 0),如果没判断就直接加到总和里,结果会变成 0 或触发 notice。必须显式跳过目录项,只对 $file->isFile() 为 true 的条目调用 filesize()

  • 注意:某些 linux 系统上,即使有读权限,stat() 系统调用也可能因 NFS 或容器挂载失败,导致 filesize() 返回 false;此时应记录警告而非中断
  • 不要用 file_exists() 前置判断——它不保证后续 filesize() 成功,反而多一次系统调用
  • 大文件(>2GB)在 32 位 PHP 中可能返回负值,建议用 $file->getSize() 替代 filesize(),它内部做了平台适配

计算超大目录时内存和超时要手动干预

遍历数万文件时,RecursiveDirectoryIterator 默认会把整个迭代器树留在内存里,加上 PHP 默认 max_execution_time=30,很容易超时或 OOM。不能靠增加 memory_limit 硬扛。

  • set_time_limit(0) 解除执行时间限制,但得搭配 ignore_user_abort(true) 防止用户关页面中断
  • 改用 Generator 分块 yield 文件大小,而不是一次性收集所有 SplFileInfo 对象
  • 对单个文件调用 clearstatcache(true, $path) 没必要;但若目录结构频繁变动,可在循环外调用 clearstatcache() 避免缓存脏数据

windows 下获取大小可能比 Linux 慢一倍

Windows 的 NTFS 不像 ext4 那样把目录大小存在 inode 里,每次 filesize()getSize() 都要走完整路径解析 + 权限检查 + 属性读取,尤其在有大量小文件或启用了杀毒软件实时扫描时,延迟明显。

立即学习PHP免费学习笔记(深入)”;

  • 若只是粗略估算,可先用 shell_exec('dir /s /a-d ' . escapeshellarg($path) . ' 2>&1') 提取最后一行数字(仅限 CLI 场景)
  • 不要在 Web 请求中调用 exec 类函数——容易被禁用,且输出格式不稳定
  • 考虑用 opcache.enable_cli=1 加速脚本自身加载,但这对 I/O 瓶颈无帮助

实际跑起来你会发现,最耗时的往往不是算法,而是某一层子目录里一个权限异常的 .git 或突然挂起的网络驱动器 —— 这类情况没法靠“优化循环”解决,得靠提前设好超时和降级逻辑。

text=ZqhQzanResources