function scanDir(string $path, int $depth = 0): void {
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS),
RecursiveIteratorIterator::SELF_FIRST
);
foreach ($iterator as $file) {
$indent = str_repeat(' ', $iterator->getDepth());
$name = htmlspecialchars($file->getFilename());
$full = $file->getPathname();
if ($file->isDir()) {
echo "{$indent}{$name}/
";
} else {
$size = $file->getSize();
echo "{$indent}{$name} ({$size} bytes)
";
}
}
}
scanDir('/var/www/html/project');
優點: 使用 SPL 迭代器,自動處理遞迴、跳過 . ..、記憶體效率佳。
function listFiles(string $dir): array {
$files = [];
if ($handle = opendir($dir)) {
while (($entry = readdir($handle)) !== false) {
if ($entry !== '.' && $entry !== '..' && $entry !== 'Thumbs.db') {
$files[] = $entry;
}
}
closedir($handle);
}
return $files;
}
function getDirSize(string $path): int {
$size = 0;
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS)
);
foreach ($iterator as $file) {
if ($file->isFile()) $size += $file->getSize();
}
return $size;
}
function formatBytes(int $bytes, int $precision = 2): string {
$units = ['B', 'KB', 'MB', 'GB', 'TB'];
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
$pow = min($pow, count($units) - 1);
return sprintf('%.*f %s', $precision, $bytes / (1024 ** $pow), $units[$pow]);
}
echo formatBytes(getDirSize('/var/www/html')); // 例:12.34 MB
set_time_limit() 或分批處理(Generator)。is_readable() 預先過濾不可讀目錄,避免例外中斷。FilesystemIterator::FOLLOW_SYMLINKS 需謹慎啟用,防止循環掃描。