stat() 返回目标文件信息,lstat() 返回符号链接自身信息;mode 是整型掩码需位运算解析;缓存需 clearstatcache() 控制;平台行为存在差异。

stat() 用来查文件元信息,但直接用容易踩坑——比如符号链接返回的是目标文件信息、缓存导致多次调用结果不一致、权限值 mode 不是八进制字符串而是整型掩码。
stat() 和 lstat() 的区别必须分清
如果你传入的是符号链接(symlink),stat() 返回的是链接指向的**目标文件**的状态;而 lstat() 返回的是**链接本身**的状态。这在检查部署路径、软链是否损坏、或审计文件结构时非常关键。
- 检查软链是否有效:先用
lstat()确认它真是个链接($stat['mode'] & 0120000),再用stat()看目标是否存在 - 误用
stat()查软链权限,可能得到目标文件的uid/gid,而非链接自身的属主(链接文件本身有独立 inode) - Windows 下注意:PHP 7.4.0 之前,NTS 版本的
stat()对符号链接的size、mtime等字段会返回链接自身值,行为不一致
stat() 返回的 mode 怎么转成 -rwxr-xr-- 这种格式
stat() 的 mode 是一个整数(如 33188),不是 0644 这样的八进制字面量,更不是字符串。直接 decoct($stat['mode']) 只能得到类似 "100644",但前三位是文件类型位,需单独解析。
- 取文件类型:用
$stat['mode'] & 0170000,比对0100000(普通文件)、0120000(链接)、040000(目录)等 - 取权限位:用
$stat['mode'] & 0777得到纯权限部分(如0644对应十进制420) - 注意 setuid/setgid/sticky 位:它们影响第 3、6、9 位的显示(
s/S、t/T),不能只靠substr(decoct(), -3) - 已有成熟逻辑可复用,比如 Laravel 的
Filesystem::permissions()或 Symfony 的Filesystem::getPermissions()内部实现
缓存问题常被忽略,clearstatcache() 不是可选操作
PHP 默认会对 stat()、file_exists()、is_dir() 等函数的结果做 realpath 缓存和 stat 缓存。这意味着:同一文件短时间内多次调用 stat(),第二次起可能返回旧值(尤其在文件被外部进程修改后)。
立即学习“PHP免费学习笔记(深入)”;
- 只清当前文件缓存:
clearstatcache(true, $filepath) - 清全部 stat 缓存(开销稍大):
clearstatcache() - 在循环中检查多个文件状态时,别在循环外只调一次
clearstatcache()—— 每次stat()前都该考虑是否需要刷新 - 如果用
fopen()+fstat(),它不受 realpath 缓存影响,但依然受 stat 缓存影响(fstat()也走同一缓存机制)
真正麻烦的从来不是怎么调用 stat(),而是你没意识到它背后有缓存、有符号链接语义、有平台差异、还有那个看着像八进制实则要位运算的 mode 字段。



















