2009-03-12 14 views
7

Domanda semplice per un newb e il mio Google-Fu mi sta fallendo. Usando PHP, come puoi contare il numero di file in una determinata directory, comprese le sottodirectory (e qualsiasi sottodirectory che potrebbero avere, ecc.)? per esempio. se la struttura della directory è la seguente:Conteggio ricorsivo di file con PHP

 
/Dir_A/ 
/Dir_A/File1.blah 
/Dir_A/Dir_B/ 
/Dir_A/Dir_B/File2.blah 
/Dir_A/Dir_B/File3.blah 
/Dir_A/Dir_B/Dir_C/ 
/Dir_A/Dir_B/Dir_C/File4.blah 
/Dir_A/Dir_D/ 
/Dir_A/Dir_D/File5.blah 

Lo script deve restituire con "5" per "./Dir_A".

Ho messo insieme le seguenti, ma non è proprio il ritorno la risposta corretta, e io non sono sicuro perché:

 
function getFilecount($path = '.', $filecount = 0, $total = 0){ 
    $ignore = array('cgi-bin', '.', '..', '.DS_Store'); 
    $dh = @opendir($path); 
    while(false !== ($file = readdir($dh))){ 
     if(!in_array($file, $ignore)){ 
      if(is_dir("$path/$file")){ 
       $filecount = count(glob("$path/$file/" . "*")); 
       $total += $filecount; 
       echo $filecount; /* debugging */ 
       echo " $total"; /* debugging */ 
       echo " $path/$file
"; /* debugging */ getFilecount("$path/$file", $filecount, $total); } } } return $total; }

Apprezzerei molto di aiuto.

risposta

15

Questo dovrebbe fare il trucco:

function getFileCount($path) { 
    $size = 0; 
    $ignore = array('.','..','cgi-bin','.DS_Store'); 
    $files = scandir($path); 
    foreach($files as $t) { 
     if(in_array($t, $ignore)) continue; 
     if (is_dir(rtrim($path, '/') . '/' . $t)) { 
      $size += getFileCount(rtrim($path, '/') . '/' . $t); 
     } else { 
      $size++; 
     } 
    } 
    return $size; 
} 
+0

Questo codice funziona esattamente come richiesto. –

+0

Ciao. Grazie per la pronta assistenza. Questo script sta causando un errore di timeout per me. "Errore irreversibile: superato il tempo di esecuzione massimo di 30 secondi". Non so perché. Ci sono solo 8 cartelle e 68 file nella directory di destinazione. – user18359

+0

Prova a ricopiare-incollando quello che è attualmente lì. La mia risposta originale ha avuto un errore in questo, questo è testato e funziona. –

0

Perché stai passando $ filecount? Il valore [passato] non è in uso; l'unico utilizzo è in "$ total + = $ filecount" e stai sovrascrivendo $ filecount poco prima.

Ti manca il caso quando la funzione incontra un file regolare (non dir).

Modifica: ho appena notato la chiamata a glob(). Non è necessario. La tua funzione tocca in modo ricorsivo ogni file nell'intero albero delle directory, comunque. Vedi la risposta di @Paolo Bergantino.

13

Utilizzare la SPL, poi vedere se è ancora ottenere un errore.

RecursiveDirectoryIterator

Esempio di utilizzo:

<?php 

$path = realpath('/etc'); 

$objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::SELF_FIRST); 
foreach($objects as $name => $object){ 
    echo "$name\n"; 
} 

?> 

di stampare un elenco di tutti i file e le directory sotto i $ percorso (incluso $ percorso ifself). Se si desidera omettere le directory, rimuovere la parte RecursiveIteratorIterator :: SELF_FIRST.

poi basta usare isdir()

+0

Questo ha fatto anche il trucco dopo averlo modificato per l'array $ ignore. Grazie! – user18359

+0

utilizza iterator_count ($ objects) per ottenere il conteggio e le prestazioni. – davidmars

-1

Controllare il manuale di PHP su glob() funzione: http://php.net/glob

Ha esempi nei commenti su come renderlo ricorsiva.

0

Paolo Bergantino era quasi con il suo codice, ma la funzione conterrà ancora i file .DS_Store da quando l'ha scritto male. Codice corretto sotto

function getFileCount($path) { 
    $size = 0; 
    $ignore = array('.','..','cgi-bin','.DS_Store'); 
    $files = scandir($path); 
    foreach($files as $t) { 
     if(in_array($t, $ignore)) continue; 
     if (is_dir(rtrim($path, '/') . '/' . $t)) { 
      $size += getFileCount(rtrim($path, '/') . '/' . $t); 
     } else { 
      $size++; 
     } 
    } 
    return $size; 
} 
0

in base alla risposta di Andrew ...

$path = realpath('my-big/directory'); 
    $objects = new RecursiveIteratorIterator(
     new RecursiveDirectoryIterator($path), 
     RecursiveIteratorIterator::SELF_FIRST 
    ); 
    $count=iterator_count($objects); 
    echo number_format($count); //680,642 wooohaah! 

del genere sono in grado di contare (non messa in vendita) migliaia & file migliaia. 680.642 file in meno di 4,6 secondi in realtà;)