
本文介绍一个健壮的 PHP 脚本,用于读取指定文本文件(如 images.txt)中的合法文件名列表,并自动删除目标目录下所有未出现在该列表中的文件,特别适用于图片资源清理场景。
本文介绍一个健壮的 php 脚本,用于读取指定文本文件(如 images.txt)中的合法文件名列表,并自动删除目标目录下所有**未出现在该列表中**的文件,特别适用于图片资源清理场景。
在实际运维或内容管理中,常需根据动态维护的白名单(如 images.txt)同步清理冗余文件。例如,/home/user/images.txt 中每行存储一个合法 JPEG 文件名(如 1.jpeg、12.jpeg),而 /home/user/images/ 目录下可能积累了大量历史文件;目标是仅保留白名单内的文件,其余全部安全删除。
原始代码失败的根本原因在于路径处理不一致:glob() 返回的是含完整路径的文件名(如 /home/user/images/15.jpeg),而 images.txt 中只存纯文件名(如 15.jpeg)。直接用 in_array($file, $array) 比较必然失败,且 unlink($directory . $file) 会造成路径重复(如 /home/user/images//home/user/images/xxx.jpeg)。
以下是修正后的完整脚本,已优化健壮性与可维护性:
<?php
// 配置路径(建议根据实际环境调整)
$whitelistFile = '/home/user/images.txt';
$targetDir = '/home/user/images/';
// 1. 安全读取白名单(自动过滤空行和换行符)
if (!file_exists($whitelistFile)) {
die("错误:白名单文件不存在 — $whitelistFile\n");
}
$allowedNames = file($whitelistFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$allowedNames = array_map('trim', $allowedNames); // 去除首尾空格
$allowedSet = array_flip($allowedNames); // 转为关联数组提升查找效率 O(1)
// 2. 获取目标目录下所有文件(支持常见图片扩展名)
$pattern = $targetDir . '*.{jpeg,jpg,png,gif,bmp}';
$files = glob($pattern, GLOB_BRACE | GLOB_NOSORT);
if ($files === false) {
die("错误:无法读取目录 — $targetDir\n");
}
// 3. 遍历并删除不在白名单中的文件
$deletedCount = 0;
foreach ($files as $fullPath) {
if (!is_file($fullPath)) continue;
$fileName = basename($fullPath);
if (!isset($allowedSet[$fileName])) {
if (unlink($fullPath)) {
echo "已删除:$fileName\n";
$deletedCount++;
} else {
echo "警告:删除失败 — $fileName(权限不足或文件被占用)\n";
}
}
}
echo "操作完成:共删除 $deletedCount 个非白名单文件。\n";
?>✅ 关键改进说明:
立即学习“PHP免费学习笔记(深入)”;
- 使用 file(..., FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) 替代 explode("\n", ...),避免空行干扰;
- 用 array_flip() 构建哈希映射,将 in_array() 的 O(n) 查找优化为 O(1),大幅提升大列表性能;
- glob() 启用 GLOB_BRACE 支持多扩展名匹配(如 *.jpg 和 *.jpeg),更贴合实际需求;
- 添加基础错误检查(文件存在性、读取失败)、权限提示及操作反馈,便于调试与生产部署;
- basename($fullPath) 精准提取文件名,确保与白名单逐字匹配(注意大小写敏感)。
⚠️ 注意事项:
- 运行前请务必备份重要数据,并在测试目录验证脚本逻辑;
- 确保 PHP 进程对目标目录拥有 read 和 write 权限(Linux 下常用 chown 或 chmod 调整);
- 白名单文件中每行应仅含文件名(不含路径),且建议统一小写以避免大小写歧义;
- 如需支持子目录递归清理,需改用 RecursiveIteratorIterator,但需谨慎评估业务需求。
此脚本兼顾简洁性与鲁棒性,可直接部署为定时任务(如 cron 每小时执行一次),实现自动化资源精简。



















