使用 scandir() 函数(最简单)

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

php 网站 列出目录
(图片来源网络,侵删)

基础示例

<?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 网站 列出目录
(图片来源网络,侵删)

基础示例

<?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,我们可以创建一个更实用的文件列表页面。

php 网站 列出目录
(图片来源网络,侵删)
<!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 唯一能递归遍历子目录的方法 相对复杂,主要用于递归场景 需要列出整个目录树(如文件管理器)

最佳实践建议:

  1. 安全第一:永远不要直接使用用户输入作为目录路径,始终使用 realpath()basename() 等函数进行验证和清理,防止目录遍历攻击(如 攻击)。
  2. 错误处理:始终使用 is_dir()is_readable() 检查目录是否存在和可读。
  3. 选择合适的方法
    • 如果只是快速看一下,用 scandir()
    • 如果需要筛选特定文件,用 glob()
    • 对于任何需要文件信息或更健壮的代码,强烈推荐使用 DirectoryIterator
    • 如果需要递归,必须使用 RecursiveDirectoryIterator