PHP

Calcolare la dimensione delle cartelle in PHP con gli iteratori SPL

calendar_today personTeam EGSOFT schedule3 min di lettura
info

Disclaimer: le informazioni pubblicate in questa sezione hanno finalità di pura divulgazione tecnica. EG Software S.r.l. non si assume alcuna responsabilità per un utilizzo improprio dei contenuti, né per eventuali danni diretti o indiretti derivanti dalla loro applicazione, e non garantisce l'aggiornamento, l'accuratezza o la completezza delle informazioni riportate. Prima di utilizzare in produzione codice o procedure qui descritte, verificane sempre l'adeguatezza al proprio contesto.

Calcolare quanto spazio occupa ciascuna sottocartella di una directory — utile per un pannello di amministrazione, o semplicemente per capire dove sta crescendo lo spazio su disco di un progetto — sembra richiedere una funzione ricorsiva scritta a mano. La libreria SPL di PHP, però, include già gli strumenti per farlo in poche righe, con un'API pensata apposta per questo tipo di attraversamento.

RecursiveDirectoryIterator e RecursiveIteratorIterator

La coppia di classi da conoscere è RecursiveDirectoryIterator, che sa scendere nelle sottocartelle, e RecursiveIteratorIterator, che la trasforma in un iteratore "piatto" su cui si può semplicemente scorrere con un foreach. Il flag LEAVES_ONLY fa sì che vengano restituiti solo i file, non le cartelle intermedie:

<?php

declare(strict_types=1);

function dimensioneCartella(string $percorso): int
{
    $totale = 0;

    $iteratore = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator(
            $percorso,
            FilesystemIterator::SKIP_DOTS | FilesystemIterator::FOLLOW_SYMLINKS
        ),
        RecursiveIteratorIterator::LEAVES_ONLY
    );

    foreach ($iteratore as $file) {
        if ($file->isFile()) {
            $totale += $file->getSize();
        }
    }

    return $totale;
}

Il flag SKIP_DOTS evita che . e .. vengano considerati come voci da attraversare — un errore facile da commettere scrivendo la ricorsione manualmente, che porterebbe a un ciclo infinito.

Un dettaglio da non sottovalutare: i permessi

Su un filesystem condiviso, alcune sottocartelle potrebbero non essere leggibili dall'utente con cui gira PHP: RecursiveDirectoryIterator lancia un'eccezione UnexpectedValueException quando incontra una cartella a cui non può accedere. In uno script pensato per girare anche su strutture di cartelle non completamente sotto il proprio controllo, conviene avvolgere la creazione dell'iteratore in un try/catch e saltare semplicemente la cartella incriminata, continuando con le altre.

Formattare la dimensione in modo leggibile

Il numero di byte grezzo va convertito nell'unità più leggibile (KB, MB, GB) in base alla grandezza, una piccola funzione di utilità che si ritrova spesso in progetti diversi:

function formattaDimensione(int $byte): string
{
    return match (true) {
        $byte >= 1_073_741_824 => number_format($byte / 1_073_741_824, 2) . ' GB',
        $byte >= 1_048_576     => number_format($byte / 1_048_576, 2) . ' MB',
        $byte >= 1_024         => number_format($byte / 1_024, 2) . ' KB',
        default                => $byte . ' B',
    };
}

Un avviso prima di metterlo online

Uno script come questo, che espone dimensioni e nomi di cartelle del server, è comodo durante lo sviluppo ma non va mai lasciato raggiungibile pubblicamente in produzione: rivela informazioni sulla struttura interna del filesystem che non riguardano un visitatore qualunque. Va protetto dietro autenticazione admin, oppure eseguito da riga di comando (CLI) invece che come pagina web pubblica.

Altri articoli su PHP grid_viewTutte le tematiche
Scrivici su WhatsApp