使用 SPL RecursiveDirectoryIterator 搭配 RecursiveIteratorIterator 可輕鬆遞迴遍歷目錄樹,累加每個檔案大小,取得目錄總佔用空間。比傳統 opendir/readdir 遞迴函式更簡潔、效能更好。
<?php
function getDirectorySize(string $path): int {
if (!is_dir($path)) {
throw new InvalidArgumentException("非目錄: $path");
}
$total = 0;
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS)
);
foreach ($iterator as $file) {
if ($file->isFile()) {
$total += $file->getSize();
}
}
return $total;
}
// 使用
$size = getDirectorySize('/var/www/html');
echo "總大小: " . formatBytes($size) . "\n";
function formatBytes(int $bytes): string {
$units = ['B', 'KB', 'MB', 'GB', 'TB'];
$i = 0;
while ($bytes >= 1024 && $i < count($units)-1) {
$bytes /= 1024;
$i++;
}
return round($bytes, 2) . ' ' . $units[$i];
}
?>
function getDirSizeDetails(string $path): array {
$result = ['total' => 0, 'dirs' => [], 'files' => 0];
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS),
RecursiveIteratorIterator::SELF_FIRST
);
foreach ($iterator as $file) {
if ($file->isDir()) {
$result['dirs'][$file->getPathname()] = 0; // 佔位
} elseif ($file->isFile()) {
$size = $file->getSize();
$result['total'] += $size;
$result['files']++;
// 累加至各父目錄(簡化版)
$dir = $file->getPath();
while ($dir !== $path && $dir !== '/') {
$result['dirs'][$dir] = ($result['dirs'][$dir] ?? 0) + $size;
$dir = dirname($dir);
}
$result['dirs'][$path] = ($result['dirs'][$path] ?? 0) + $size;
}
}
return $result;
}
FilesystemIterator::SKIP_DOTS:自動跳過 . 和 ..。FilesystemIterator::CURRENT_AS_FILEINFO:預設即為 SplFileInfo,支援 getSize()、isFile()、getPathname() 等。RecursiveIteratorIterator::SELF_FIRST:先處理目錄本身再處理子元素(適合建立樹狀結構)。CHILD_FIRST:先處理子元素(適合刪除操作)。du -sh(Linux)。try-catch 或 @ 抑制。SPL 迭代器是 PHP 檔案系統操作的現代標準工具,程式碼可讀性與維護性遠勝傳統函式。