首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 計算目錄總大小:RecursiveDirectoryIterator 一行代碼搞定遞歸求和

     編輯:PHP 綜合知識

前言

獲取目錄及其所有子目錄下文件的總大小,是磁盤配額統計、備份評估、存儲監控的常見需求。利用 SPL 的 RecursiveDirectoryIterator 與 RecursiveIteratorIterator,只需一個 foreach 即可完成遞歸求和,無需手寫遞歸函數。

核心代碼

<?php
$dirPath = 'C:\\wamp'; // 或 /var/www/html

$iterator = new RecursiveIteratorIterator(
    new RecursiveDirectoryIterator($dirPath, FilesystemIterator::SKIP_DOTS)
);

$totalSize = 0;
foreach ($iterator as $file) {
    if ($file->isFile()) { // 僅統計文件,跳過目錄、鏈接等
        $totalSize += $file->getSize();
    }
}

// 友好輸出
echo "總大小:$totalSize 字節\n";
echo "約 " . round($totalSize / 1024 / 1024, 2) . " MB\n";
?>

關鍵點解析

  1. FilesystemIterator::SKIP_DOTS:自動忽略 . 和 ..,避免無限循環。
  2. RecursiveIteratorIterator 預設為 LEAVES_ONLY(僅葉子節點),但為了語義清晰,示例中顯式判斷 $file->isFile()。
  3. SplFileInfo::getSize() 返回文件大小(字節),直接累加即可。
  4. 遍歷過程中不打開文件內容,僅讀取元數據,速度極快。

進階:封裝為可複用函數並支援人類可讀格式

<?php
/**
 * 計算目錄總大小
 *
 * @param string $dir 目錄路徑
 * @param bool   $humanReadable 是否返回易讀字符串(如 1.23 MB)
 * @return int|string 字節數或格式化字符串
 */
function getDirectorySize(string $dir, bool $humanReadable = false)
{
    if (!is_dir($dir)) {
        return $humanReadable ? '0 B' : 0;
    }

    $rii = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS)
    );

    $bytes = 0;
    foreach ($rii as $file) {
        if ($file->isFile()) {
            $bytes += $file->getSize();
        }
    }

    if (!$humanReadable) {
        return $bytes;
    }

    $units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
    $i = 0;
    while ($bytes >= 1024 && $i < count($units) - 1) {
        $bytes /= 1024;
        $i++;
    }
    return round($bytes, 2) . ' ' . $units[$i];
}

// 使用示例
echo "原始字節:" . getDirectorySize('/var/log') . "\n";
echo "易讀格式:" . getDirectorySize('/var/log', true) . "\n"; // 輸出:12.45 MB
?>

性能與注意事項

  • 大目錄耗時:包含百萬級文件時遍歷可能耗時數秒,建議異步執行或緩存結果。
  • 權限問題:遇到無讀取權限的子目錄會拋出 UnexpectedValueException,生產環境建議用 try-catch 包裹或設置 FilesystemIterator::FOLLOW_SYMLINKS 視情況決定是否跟隨鏈接。
  • 符號鏈接:預設不跟隨符號鏈接(SKIP_DOTS 不包含此行為),若需統計鏈接目標大小,可添加 FilesystemIterator::FOLLOW_SYMLINKS 旗標。
  • Windows 路徑:使用雙反斜杠 C:\\path 或正斜杠 C:/path 均可。

對比:du 命令 vs PHP 實現

維度shell_exec('du -sh ...')PHP RecursiveIterator
速度極快(C 級實現)較快(PHP 級遍歷)
跨平台依賴 Linux/Unix 工具純 PHP,全平台通用
可控性難以過濾特定文件/擴展名可在循環中任意邏輯過濾
安全性命令注入風險需 escapeshellarg無注入風險

總結

利用 RecursiveDirectoryIterator + RecursiveIteratorIterator 計算目錄大小,代碼極其精簡、跨平台、可擴展。只需幾行代碼即可替代繁瑣的手寫遞歸,是 PHP 文件系統操作的最佳實踐之一。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved