php无一键导出文件夹列表函数,需用scandir()、recursivedirectoryiterator或glob()实现;关键在导出为csv/txt/json时处理bom、换行符、字段包裹及路径编码,避免中文乱码与excel解析错误。

PHP 本身不提供“一键导出文件夹列表”的内置函数,但用 scandir()、RecursiveDirectoryIterator 或 glob() 就能可靠生成目录清单——关键不在“怎么列”,而在“怎么导出成可用格式”(如 CSV、TXT、JSON)且避免权限、符号链接、编码等坑。
用 scandir() 递归列出所有子目录和文件(基础但可控)
适合中小目录结构,逻辑清晰,便于加过滤和排序。注意它默认包含 . 和 ..,必须手动剔除;Windows 路径分隔符需统一为正斜杠或转义,否则 CSV 导出时可能损坏格式。
- 用
array_filter()去掉.和..:array_filter(scandir($path), fn($f) => !in_array($f, ['.', '..'])) - 递归时建议用函数封装,避免深度过大导致栈溢出;超过 10 层嵌套建议改用迭代方式
- 中文路径在 Windows 下容易乱码:确保脚本文件保存为 UTF-8 无 BOM,且输出前调用
mb_internal_encoding('UTF-8') - 示例片段(仅当前层):
$files = array_filter(scandir('/var/www'), fn($f) => !in_array($f, ['.', '..']));
用 RecursiveDirectoryIterator 生成带元数据的清单(推荐用于正式导出)
比 scandir() 更健壮,自动跳过不可读目录、处理符号链接(可选)、支持获取修改时间、大小、类型等字段,是生成带详情清单的首选。
- 构造时传入
FilesystemIterator::SKIP_DOTS可省去手动过滤./.. - 用
getRealPath()获取绝对路径,避免相对路径在导出后无法定位;但注意若目录无读取权限,getRealPath()返回false,需判空 - 遍历时用
isDir()和isFile()区分类型,别依赖扩展名判断 - 导出 CSV 时,文件名含逗号、换行或双引号必须用双引号包裹并转义:例如
"\"file,name.txt\""
导出为 CSV 文件时必须处理的三个细节
看似简单,但多数 PHP 目录导出脚本在这里翻车:中文乱码、字段截断、Excel 打开显示“安全警告”。根本原因不是 PHP,而是 Excel 对 CSV 的解析规则。
立即学习“PHP免费学习笔记(深入)”;
- 文件开头必须写入 UTF-8 BOM(
\xEF\xBB\xBF),否则 Excel 在 Windows 上默认用 ANSI 解析中文 - 每行末尾必须是
\r\n(Windows 换行),仅\n可能导致 Excel 合并多行为单行 - 所有字段(包括路径)都应强制用双引号包裹,哪怕不含特殊字符;否则
C:\Program Files这类含空格路径会被 Excel 当作多个字段 - 不要用
fputcsv()直接写,它不自动加 BOM,也不保证\r\n:先fopen(),写 BOM,再逐行fwrite($fp, '"' . addslashes($path) . "\"\r\n")
为什么不用 shell_exec('ls -R') 或 exec('dir /s')?
看起来最省事,实际埋雷最多:跨平台失效、权限隔离失败、输出格式不可控、无法捕获错误码、易被注入攻击(尤其路径来自用户输入)。
- Linux 下
ls -R输出含多余空行和分隔线,解析成本高;Windowsdir /s时间格式随系统语言变化(如“2024/05/20” vs “2024-05-20”) - Web 服务器通常禁用 shell 函数,
disable_functions里大概率有exec、shell_exec - 若路径含空格或特殊字符(如
$HOME/test dir),未加引号直接拼接命令会报错或执行意外路径 - 真正需要 Shell 的场景(比如超大目录快速扫描),应改用
proc_open()配合流式读取,而非exec()
真正难的不是“列出”,而是让导出结果在不同系统、不同软件里稳定可读——BOM、换行符、字段包裹、路径编码,这四点漏掉任一,用户双击打开 CSV 就会看到一堆问号或错位。别信“本地测试没问题”,一定要用目标环境(尤其是客户用的 Windows + Excel)验证输出文件头和换行。









