<?php
/**
* 遞歸掃描並輸出目錄樹
* @param string $dir 絕對路徑(需以 / 或 \ 結尾)
* @param int $level 當前層級(內部使用,外部調用默認 1)
* @return int 文件總數
*/
function scanDirTree(string $dir, int $level = 1): int {
static $fileCount = 0; // 靜態變量跨遞歸累計
// 1. 打開目錄(抑制警告)
$handle = @opendir($dir);
if (!$handle) {
// 僅頂層報錯,避免遞歸中重複輸出
if ($level === 1) {
die("❌ 目錄打開失敗:$dir (請檢查路徑是否存在、權限是否足夠)");
}
return $fileCount;
}
// 2. 遍歷條目
while (($entry = readdir($handle)) !== false) {
// 跳過 . 和 ..
if ($entry === '.' || $entry === '..') continue;
$fileCount++;
$fullPath = $dir . $entry;
// 3. 輸出縮進
echo str_repeat(' ', ($level - 1) * 4);
// 4. 區分目錄/文件
if (is_dir($fullPath)) {
// 目錄:粗體 + 可點擊展開(需前端 JS 配合)+ 遞歸
echo "<strong><a href=\"#\" data-path=\"" . htmlspecialchars($fullPath) . "\">" . htmlspecialchars($entry) . "</a></strong><br>";
scanDirTree($fullPath . DIRECTORY_SEPARATOR, $level + 1);
} else {
// 文件:普通超鏈接
echo "<a href=\"" . htmlspecialchars($fullPath) . "\" target=\"_blank\">" . htmlspecialchars($entry) . "</a><br>";
}
}
closedir($handle);
// 5. 頂層輸出統計
if ($level === 1) {
echo "<hr><strong>文件總數:$fileCount</strong>";
}
return $fileCount;
}
// 使用示例
// 確保路徑以分隔符結尾
$targetDir = 'D:/wamp/www/test/lamp61/';
if (substr($targetDir, -1) !== DIRECTORY_SEPARATOR) {
$targetDir .= DIRECTORY_SEPARATOR;
}
echo "<h3>目錄樹:$targetDir</h3>";
scanDirTree($targetDir);
?>
<?php
/**
* 獲取目錄樹結構數組
* @return array ['dirs'=>[], 'files'=>[], 'count'=>int]
*/
function getDirTree(string $dir): array {
$result = ['dirs' => [], 'files' => [], 'count' => 0];
$handle = @opendir($dir);
if (!$handle) return $result;
while (($entry = readdir($handle)) !== false) {
if ($entry === '.' || $entry === '..') continue;
$fullPath = $dir . DIRECTORY_SEPARATOR . $entry;
$result['count']++;
if (is_dir($fullPath)) {
$result['dirs'][$entry] = getDirTree($fullPath); // 遞歸
} else {
$info = stat($fullPath);
$result['files'][$entry] = [
'size' => $info['size'],
'mtime' => $info['mtime'],
'mime' => mime_content_type($fullPath) ?: 'unknown',
'path' => $fullPath,
];
}
}
closedir($handle);
return $result;
}
// 輸出 JSON 供前端樹形組件(如 zTree, jstree, Element UI Tree)渲染
header('Content-Type: application/json; charset=utf-8');
echo json_encode(getDirTree('/var/www/html'), JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
<?php
$dir = new RecursiveDirectoryIterator('/var/www/html', FilesystemIterator::SKIP_DOTS);
$iter = new RecursiveIteratorIterator($dir, RecursiveIteratorIterator::SELF_FIRST);
foreach ($iter as $path => $file) {
$depth = $iter->getDepth();
$indent = str_repeat(' ', $depth);
$type = $file->isDir() ? '[DIR] ' : '[FILE]';
echo "$indent$type{$file->getFilename()}\n";
}
優勢:內建跳過 ./..、可組合 RegexIterator 過濾擴展名、CallbackFilterIterator 自定義邏輯、自動處理跨平台路徑分隔符。
yield 分批輸出。realpath() 規範化並校驗在允許根目錄內。readfile() + 權限檢查)提供文件訪問。