項目部署、版本核對、安全審計常需生成目錄下所有文件的 路徑 → [大小, MD5] 映射清單。本文提供一個健壯的類實現,支持忽略列表、相對路徑輸出、命名空間封裝、自動生成 PHP 類文件。
<?php
class TestGenerate {
public static $appFolder = '';
public static $ignorePaths = ['xxxx/xxx.php']; // 相對路徑忽略列表
public static function start() {
$appPath = 'E:\\myApp'; // 應用根目錄
$destFile = 'E:\\temp2\\dest.md5.txt';
self::$appFolder = $appPath;
$handle = fopen($destFile, 'w+');
self::writeHeader($handle);
self::traverse($appPath, $handle);
self::writeFooter($handle);
fclose($handle);
echo "清單生成完成: $destFile";
}
// 遞歸遍歷
public static function traverse($path, $handle) {
if (!file_exists($path) || !is_dir($path)) return;
if (!($dh = opendir($path))) return;
while (($file = readdir($dh)) !== false) {
if ($file === '.' || $file === '..') continue;
$full = $path . DIRECTORY_SEPARATOR . $file;
if (is_dir($full)) {
self::traverse($full, $handle); // 遞歸
} else {
self::writeFileRecord($full, $handle);
}
}
closedir($dh);
}
// 寫入單文件記錄
public static function writeFileRecord($filePath, $handle) {
if (!file_exists($filePath)) return;
// 相對路徑統一為正斜杠
$rel = str_replace('\\', '/', str_replace(self::$appFolder . DIRECTORY_SEPARATOR, '', $filePath));
// 忽略 tmp 目錄
if (strpos($rel, 'tmp/') === 0) return;
// 忽略列表匹配
if (in_array($rel, self::$ignorePaths)) return;
$size = filesize($filePath);
$md5 = @md5_file($filePath);
if ($md5 === false) return; // 讀取失敗跳過
$line = "\t\t\"$rel\" => array(\"$size\", \"$md5\"),\n";
fwrite($handle, $line);
}
// 生成文件頭 (PHP 類結構)
public static function writeHeader($handle) {
$header = <<
生成文件示例 (dest.md5.txt)
<?php
// Auto-generated on 2024-01-15 10:30:00
namespace test;
class MyFile {
static $allFiles = array(
"index.php" => array("2456", "a1b2c3d4e5f6..."),
"config/database.php" => array("1024", "f6e5d4c3b2a1..."),
"lib/Core/Database.php" => array("15872", "1234567890ab..."),
// ...
);
}
驗證使用示例
require 'dest.md5.txt'; // 自動加載 test\MyFile
$files = test\MyFile::$allFiles;
foreach ($files as $rel => $info) {
$full = __DIR__ . '/' . $rel;
if (!file_exists($full)) {
echo "[缺失] $rel\n";
continue;
}
if (filesize($full) != $info[0]) {
echo "[大小異常] $rel\n";
}
if (md5_file($full) != $info[1]) {
echo "[內容篡改] $rel\n";
}
}
echo "完整性校驗完成。\n";
增強建議
- 流式 MD5:大文件用
hash_init('md5') + hash_update_stream() 避免內存峰值。
- 並行處理:配合
pcntl_fork 或多進程分目錄計算,提升大項目速度。
- 增量更新:對比上次清單 mtime,僅處理變更文件。
- 簽名防篡改:清單生成後用私鑰簽名,驗證時校驗簽名。