scandir() 默认按字典序(ASCII码)升序排列,. 和 .. 恒居首位;file10.txt 会排在 file2.txt 前,因其'1'

PHP 中 scandir() 默认排序规则是什么
scandir() 返回的数组默认按字典序(ASCII 码顺序)升序排列,. 和 .. 总是排在最前面,之后才是其他文件/文件夹。这不是“自然排序”,比如 file10.txt 会排在 file2.txt 前面——因为 '1' 的 ASCII 值小于 '2'。
如果你期望 file2 → file10 这样的顺序,直接用 scandir() 不行,得手动干预。
如何让文件夹按名称自然排序(含数字)
用 natsort() 是最常用、最稳妥的方式,它专为人类可读的字符串设计,能正确解析 folder1、folder10 的大小关系。
- 注意:
natsort()会重置键名,如果需要保留原始键(比如索引对应路径),改用natcasesort()或配合array_values() - 对文件夹单独过滤后再排序更安全:先用
is_dir()筛出目录项,再natsort() - 示例片段:
$items = scandir('/path/to/dir');
$dirs = array_filter($items, function($item) use ($path) {
return $item !== '.' && $item !== '..' && is_dir($path . '/' . $item);
});
$dirs = array_values($dirs); // 重索引
natsort($dirs); // 自然排序
按修改时间或大小排序文件夹
PHP 没有内置函数直接按时间/大小对目录名排序,必须获取元数据再自定义比较。核心是用 usort() + filemtime() 或 filesize()。
立即学习“PHP免费学习笔记(深入)”;
-
filemtime()获取最后修改时间戳;filesize()对目录返回不准确(通常为 4096 字节),应改用disk_total_space()或跳过目录大小比较 - 务必用
realpath()或拼接完整路径,否则filemtime('subdir')会失败 - 示例(按修改时间倒序):
$dirs = array_filter(scandir('/path/to/dir'), function($i) use ($base) {
return $i !== '.' && $i !== '..' && is_dir($base . '/' . $i);
});
usort($dirs, function($a, $b) use ($base) {
$timeA = filemtime($base . '/' . $a);
$timeB = filemtime($base . '/' . $b);
return $timeB <=> $timeA; // 降序
});
为什么 sort() 和 rsort() 不适合文件夹名排序
sort() 是纯 ASCII 排序,会导致 z1 排在 a10 后面(因为 'z' > 'a'),但数字部分又错乱;rsort() 只是反向,问题一样。更隐蔽的问题是:它们对中文、emoji、带空格或特殊符号的目录名行为不可控,且不区分大小写(除非加 SORT_FLAG_CASE)。
真正需要稳定可控的顺序时,别图省事直接套 sort(),尤其是用户上传的文件夹名不可预测时。
自然排序和时间排序都得自己构造逻辑,没有银弹——关键不是“怎么排”,而是“你依赖什么维度做决策”。比如管理后台按时间倒序展示最新上传的目录,就别用 natsort()。











