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

PHP 遞迴計算目錄大小:自訂 dirSize() 函數完整實作與優化建議

     編輯:PHP 綜合知識

PHP 內建 filesize() 僅能取得單一檔案大小,**缺乏直接計算目錄總大小的函數**。本文示範如何以**遞迴演算法**實作 dirSize(),正確處理子目錄、排除特殊目錄、單位換算,並提供效能優化與替代方案討論。

一、核心遞迴邏輯

  1. 開啟目錄控制代碼(opendir)。
  2. 迴圈 readdir 讀取每個條目。
  3. **排除 . 與 ..** 避免無限遞迴。
  4. 組合完整路徑 $sub = $dir . '/' . $entry。
  5. is_dir($sub) → 遞迴呼叫 dirSize($sub) 累加。
  6. is_file($sub) → filesize($sub) 累加。
  7. 關閉控制代碼,回傳總位元組數。

二、標準實作程式碼

<?php
function dirSize(string $directory): int {
    $total = 0;
    $handle = @opendir($directory);
    if (!$handle) return 0; // 無權限或不存在視為 0

    while (($entry = readdir($handle)) !== false) {
        if ($entry === '.' || $entry === '..') continue;
        $path = $directory . '/' . $entry;

        if (is_dir($path)) {
            $total += dirSize($path); // 遞迴
        } elseif (is_file($path)) {
            $total += filesize($path);
        }
        // 略過 link、socket 等特殊類型
    }
    closedir($handle);
    return $total;
}

// 使用範例
$bytes = dirSize('phpMyAdmin');
echo '目錄大小:' . round($bytes / 1024, 2) . ' KB';
echo ' / ' . round($bytes / 1024 / 1024, 2) . ' MB';
?>

三、進階優化版(支援快取、排除模式、大檔案安全)

function dirSizeAdvanced(string $dir, array $options = []): int {
    static $cache = []; // 簡易記憶體快取,避免同目錄重複計算
    $key = realpath($dir);
    if ($key && isset($cache[$key])) return $cache[$key];

    $exclude = $options['exclude'] ?? ['.git', 'node_modules', 'vendor', 'storage/logs'];
    $followLinks = $options['follow_links'] ?? false;

    $total = 0;
    $handle = @opendir($dir);
    if (!$handle) return 0;

    while (($entry = readdir($handle)) !== false) {
        if ($entry === '.' || $entry === '..') continue;
        if (in_array($entry, $exclude, true)) continue;

        $path = $dir . '/' . $entry;

        if (is_link($path)) {
            if (!$followLinks) continue;
            $path = readlink($path); // 解析連結實際路徑
        }

        if (is_dir($path)) {
            $total += dirSizeAdvanced($path, $options);
        } elseif (is_file($path)) {
            $sz = @filesize($path);
            if ($sz !== false) $total += $sz;
        }
    }
    closedir($handle);

    if ($key) $cache[$key] = $total;
    return $total;
}

四、替代方案比較

方案優點缺點適用場景
PHP 遞迴 (本文)純 PHP、跨平台、可自訂邏輯大量檔案/深層目錄效能較差、受 max_execution_time 限制中小型專案、需自訂排除規則
exec('du -sh ...')極快、系統級優化需 exec 權限、僅 Linux/Unix、安全風險、跨平台差內部管理工具、Linux 伺服器環境
SPL RecursiveDirectoryIterator物件導向、可搭配 FilterIterator記憶體佔用較大、速度略慢於原生函數現代框架專案、需複雜過濾

五、實務注意事項

  • 權限問題:opendir/filesize 可能因權限回傳 false,務必用 @ 抑制警告並檢查回傳值。
  • 符號連結循環:遞迴前檢查 is_link(),決定是否跟隨或略過。
  • 超大目錄:考慮將計算任務放入背景隊列(如 Laravel Queue、Gearman),避免阻塞 HTTP 請求。
  • 單位換算:建議封裝 formatBytes($bytes, $precision=2) 統一輸出 KB/MB/GB/TB。

掌握遞迴目錄大小計算,能為檔案管理面板、備份系統、磁碟配額監控等功能提供核心資料支撐。

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