
scandir()默认返回当前目录(.)和父目录(..)条目,这是posix标准行为;实际遍历文件前需显式过滤这两项,否则会导致逻辑错误或意外输出。
scandir()默认返回当前目录(.)和父目录(..)条目,这是posix标准行为;实际遍历文件前需显式过滤这两项,否则会导致逻辑错误或意外输出。
scandir() 是 PHP 中用于读取指定目录下所有文件与子目录名称的内置函数。它按字典序返回一个包含所有条目的数组,但该结果始终包含两个特殊目录项:.(代表当前目录)和 ..(代表上级目录)。这并非 bug,而是底层操作系统(如 Linux/macOS/Windows 的兼容层)对目录结构的标准表示,PHP 忠实保留了这一语义。
例如,执行以下代码:
$carpet_images = scandir('./images');
print_r($carpet_images);输出为:
Array
(
[0] => .
[1] => ..
[2] => 1562475195-1796949251.jpg
[3] => 5f931b6fdbbdc8bfbd164f4bb08334ec_zzz-1.jpg
)其中 [0] 和 [1] 对应的 . 与 .. 并非真实文件,若直接用于文件操作(如 is_file()、file_get_contents() 或 HTML 渲染),将引发警告、空结果或路径越界风险。
立即学习“PHP免费学习笔记(深入)”;
✅ 推荐解决方案:使用 array_filter() 安全剔除特殊条目
$directories = scandir('./images');
$carpet_images = array_filter($directories, function($item) {
return !in_array($item, ['.', '..'], true);
});
// 注意:array_filter 会保留原键名,如需重置索引,可追加 array_values()
$carpet_images = array_values($carpet_images);? 关键注意事项:
- ✅ 始终使用严格比较(true 参数传入 in_array),避免字符串 '0' 等意外匹配;
- ✅ 若需进一步区分文件与目录,建议在过滤后结合 is_file() 或 is_dir() 进行二次判断;
- ⚠️ 不要依赖 unset($arr[0], $arr[1]) —— 当目录为空或权限受限时,返回数组结构可能变化,硬编码键值易出错;
- ? 更现代的替代方案是使用 glob('./images/*')(仅匹配非隐藏文件)或 DirectoryIterator 类(面向对象、支持更多元数据)。
总结:scandir() 的 . 和 .. 是设计使然,不是错误。专业实践中应将其视为“元信息”,在业务逻辑前统一过滤,确保后续处理的对象均为真实目录成员。











