使用 scandir() 函数(最简单)
scandir() 是最直接、最简单的方法,它返回一个包含所有文件和目录名称的数组。

(图片来源网络,侵删)
基础示例
<?php
// 指定要列出的目录路径
$directory = './images/'; // './' 表示当前目录,'../' 表示上级目录
// 检查目录是否存在且可读
if (is_dir($directory) && is_readable($directory)) {
// scandir() 获取目录下的所有文件和文件夹
$files = scandir($directory);
// 遍历数组并打印
foreach ($files as $file) {
// 跳过当前目录 '.' 和上级目录 '..'
if ($file != '.' && $file != '..') {
echo $file . '<br>';
}
}
} else {
echo "目录不存在或不可读: " . htmlspecialchars($directory);
}
?>
scandir() 的排序选项
scandir() 有第二个可选参数,可以控制排序顺序:
SCANDIR_SORT_NONE(默认): 不排序。SCANDIR_SORT_ASCENDING: 按字母升序排序 (A-Z)。SCANDIR_SORT_DESCENDING: 按字母降序排序 (Z-A)。
// 按升序排序 $files = scandir($directory, SCANDIR_SORT_ASCENDING); // 按降序排序 $files = scandir($directory, SCANDIR_SORT_DESCENDING);
使用 glob() 函数(更灵活)
glob() 函数可以根据指定的模式(类似通配符)来查找文件路径,非常灵活。
基础示例
<?php
$directory = './images/';
// 查找目录下所有文件和目录
$files = glob($directory . '*');
// 遍历并打印文件名
foreach ($files as $file) {
// basename() 获取路径中的文件名部分
echo basename($file) . '<br>';
}
?>
glob() 的高级用法
你可以轻松地筛选特定类型的文件,例如只列出 .jpg 文件:
<?php
$directory = './images/';
// 只查找 .jpg 文件
$jpg_files = glob($directory . '*.jpg');
// 只查找 .png 和 .gif 文件
$image_files = glob($directory . '{*.png,*.gif}', GLOB_BRACE);
// 遍历并打印
foreach ($image_files as $file) {
echo basename($file) . '<br>';
}
?>
使用 DirectoryIterator 类(面向对象,功能强大)
这是 PHP 提供的面向对象的、更强大、更安全的方式,它是一个文件系统迭代器,可以让你像遍历数组一样遍历目录,并且提供了更多文件信息的方法。

(图片来源网络,侵删)
基础示例
<?php
$directory = new DirectoryIterator('./images/');
// foreach 会自动处理目录句柄的打开和关闭
foreach ($directory as $fileinfo) {
// 跳过当前目录 '.' 和上级目录 '..'
if ($fileinfo->isDot()) {
continue;
}
echo $fileinfo->getFilename() . '<br>';
}
?>
DirectoryIterator 的优势
它提供了丰富的内置方法来获取文件信息,非常方便:
<?php
$directory = new DirectoryIterator('./images/');
foreach ($directory as $fileinfo) {
if ($fileinfo->isDot()) {
continue;
}
$filename = $fileinfo->getFilename();
$filesize = $fileinfo->getSize(); // 获取文件大小(字节)
$isFile = $fileinfo->isFile(); // 判断是否为文件
$isDir = $fileinfo->isDir(); // 判断是否为目录
$lastModified = $fileinfo->getMTime(); // 获取最后修改时间 (时间戳)
echo "文件名: " . $filename . "<br>";
echo "大小: " . $filesize . " bytes<br>";
echo "类型: " . ($isFile ? '文件' : '目录') . "<br>";
echo "修改时间: " . date('Y-m-d H:i:s', $lastModified) . "<br>";
echo "-------------------------<br>";
}
?>
使用 RecursiveDirectoryIterator 类(递归列出子目录)
如果你想列出目录及其所有子目录中的文件,这个类是最佳选择。
基础示例
<?php
$directory = './images/';
// 创建一个递归目录迭代器
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS)
);
// 遍历所有文件和目录
foreach ($iterator as $fileinfo) {
// $iterator->getDepth() 可以获取文件的深度层级
$indent = str_repeat('---', $iterator->getDepth());
echo $indent . $fileinfo->getFilename() . '<br>';
}
?>
输出示例:
logo.png
---banner.jpg
---subfolder1
------photo1.jpg
------photo2.jpg
---subfolder2
------icon.png
完整的实用示例:生成一个美观的文件列表
结合 DirectoryIterator 和一些 HTML/CSS,我们可以创建一个更实用的文件列表页面。

(图片来源网络,侵删)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">目录列表</title>
<style>
body { font-family: sans-serif; line-height: 1.6; padding: 20px; }
table { width: 100%; border-collapse: collapse; margin-top: 20px; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
th { background-color: #f2f2f2; }
tr:nth-child(even) { background-color: #f9f9f9; }
.icon { margin-right: 10px; }
.folder-icon { color: #FFA500; }
.file-icon { color: #1E90FF; }
</style>
</head>
<body>
<h1>目录内容: <?php echo htmlspecialchars($_GET['dir'] ?? '.'); ?></h1>
<?php
// 安全地获取目录参数
$base_dir = __DIR__; // 定义一个安全的根目录,例如当前脚本所在目录
$requested_dir = isset($_GET['dir']) ? $_GET['dir'] : '.';
// 防止目录遍历攻击
$full_path = realpath($base_dir . '/' . $requested_dir);
// 检查路径是否在允许的根目录下
if (strpos($full_path, $base_dir) !== 0) {
die("错误:访问被拒绝。");
}
if (is_dir($full_path)) {
$iterator = new DirectoryIterator($full_path);
echo '<table>';
echo '<tr><th>名称</th><th>类型</th><th>大小</th><th>修改时间</th></tr>';
foreach ($iterator as $fileinfo) {
if ($fileinfo->isDot()) {
continue;
}
$filename = htmlspecialchars($fileinfo->getFilename());
$is_dir = $fileinfo->isDir();
$type = $is_dir ? '目录' : '文件';
$size = $is_dir ? '-' . $fileinfo->getSize() : formatFileSize($fileinfo->getSize());
$modified_date = date('Y-m-d H:i:s', $fileinfo->getMTime());
$icon_class = $is_dir ? 'folder-icon' : 'file-icon';
echo '<tr>';
echo '<td><span class="icon ' . $icon_class . '">📁</span>' . $filename . '</td>';
echo '<td>' . $type . '</td>';
echo '<td>' . $size . '</td>';
echo '<td>' . $modified_date . '</td>';
echo '</tr>';
}
echo '</table>';
} else {
echo "<p>错误:指定的路径不是一个目录或不存在。</p>";
}
// 辅助函数:格式化文件大小
function formatFileSize($bytes) {
if ($bytes < 1024) {
return $bytes . ' B';
} elseif ($bytes < 1048576) {
return round($bytes / 1024, 2) . ' KB';
} else {
return round($bytes / 1048576, 2) . ' MB';
}
}
?>
</body>
</html>
总结与建议
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
scandir() |
简单易用,代码少 | 功能有限,返回原始数组 | 快速、简单的目录列表需求 |
glob() |
灵活,支持模式匹配 | 主要用于查找文件,不如迭代器功能全面 | 需要根据文件名模式筛选时 |
DirectoryIterator |
面向对象,功能强大,代码清晰 | 需要理解基本的OOP概念 | 推荐的通用方法,特别是需要获取文件详细信息时 |
RecursiveDirectoryIterator |
唯一能递归遍历子目录的方法 | 相对复杂,主要用于递归场景 | 需要列出整个目录树(如文件管理器) |
最佳实践建议:
- 安全第一:永远不要直接使用用户输入作为目录路径,始终使用
realpath()、basename()等函数进行验证和清理,防止目录遍历攻击(如 攻击)。 - 错误处理:始终使用
is_dir()和is_readable()检查目录是否存在和可读。 - 选择合适的方法:
- 如果只是快速看一下,用
scandir()。 - 如果需要筛选特定文件,用
glob()。 - 对于任何需要文件信息或更健壮的代码,强烈推荐使用
DirectoryIterator。 - 如果需要递归,必须使用
RecursiveDirectoryIterator。
- 如果只是快速看一下,用
