PHP подсчет общего количества файлов в каталоге и функция подкаталога

Мне нужно получить общее количество файлов JPG в указанном каталоге, включая ВСЕ его подкаталоги. Нет вложенных каталогов.

Структура выглядит следующим образом:

dir1/
2 files  
   subdir 1/
       8 files

общее Dir1 = 10 файлов

dir2/ 
    5 files  
    subdir 1/ 
        2 files  
    subdir 2/ 
        8 files

общее Dir2 = 15 файлов

У меня есть эта функция, которая не работает нормально, так как она считает только файлы в последнем подкаталоге, а общее количество в 2 раза больше, чем фактическое количество файлов. (выведет 80, если у меня будет 40 файлов в последнем подкаталоге)

public function count_files($path) { 
global $file_count;

$file_count = 0;
$dir = opendir($path);

if (!$dir) return -1;
while ($file = readdir($dir)) :
    if ($file == '.' || $file == '..') continue;
    if (is_dir($path . $file)) :
        $file_count += $this->count_files($path . "/" . $file);
    else :
        $file_count++;
    endif;
endwhile;

closedir($dir);
return $file_count;
}

Ответы на вопрос(5)

Решение Вопроса

Для забавы я взбил это вместе:

class FileFinder
{
    private $onFound;

    private function __construct($path, $onFound, $maxDepth)
    {
        // onFound gets called at every file found
        $this->onFound = $onFound;
        // start iterating immediately
        $this->iterate($path, $maxDepth);
    }

    private function iterate($path, $maxDepth)
    {
        $d = opendir($path);
        while ($e = readdir($d)) {
            // skip the special folders
            if ($e == '.' || $e == '..') { continue; }
            $absPath = "$path/$e";
            if (is_dir($absPath)) {
                // check $maxDepth first before entering next recursion
                if ($maxDepth != 0) {
                    // reduce maximum depth for next iteration
                    $this->iterate($absPath, $maxDepth - 1);
                }
            } else {
                // regular file found, call the found handler
                call_user_func_array($this->onFound, array($absPath));
            }
        }
        closedir($d);
    }

    // helper function to instantiate one finder object
    // return value is not very important though, because all methods are private
    public static function find($path, $onFound, $maxDepth = 0)
    {
        return new self($path, $onFound, $maxDepth);
    }
}

// start finding files (maximum depth is one folder down) 
$count = $bytes = 0;
FileFinder::find('.', function($file) use (&$count, &$bytes) {
    // the closure updates count and bytes so far
    ++$count;
    $bytes += filesize($file);
}, 1);

echo "Nr files: $count; bytes used: $bytes\n";

Вы передаете базовый путь, найденный обработчик и максимальную глубину директории (-1 для отключения). Найденный обработчик - это функция, которую вы определяете снаружи, ему передается имя пути относительно пути, указанного вfind() функция.

Надеюсь, это имеет смысл и поможет тебе

Вы можете сделать это, используя RecursiveDirectoryIterator

<?php
function scan_dir($path){
    $ite=new RecursiveDirectoryIterator($path);

    $bytestotal=0;
    $nbfiles=0;
    foreach (new RecursiveIteratorIterator($ite) as $filename=>$cur) {
        $filesize=$cur->getSize();
        $bytestotal+=$filesize;
        $nbfiles++;
        $files[] = $filename;
    }

    $bytestotal=number_format($bytestotal);

    return array('total_files'=>$nbfiles,'total_size'=>$bytestotal,'files'=>$files);
}

$files = scan_dir('./');

echo "Total: {$files['total_files']} files, {$files['total_size']} bytes\n";
//Total: 1195 files, 357,374,878 bytes 
?>
 Lawrence Cherone05 июн. 2012 г., 12:44
Нет проблем. рад помоч
 Ja͢ck05 июн. 2012 г., 14:11
@ Neoweiter, это тоже сканирует подкаталоги, я думал, что вы специально хотели только до уровня подкаталога?
 Neoweiter05 июн. 2012 г., 12:42
Спасибо Лоуренс! Это сработало отлично
 Neoweiter05 июн. 2012 г., 15:10
@ jack, я не буду использовать sub sub dirs, но если скрипт его ищет, это не так важно;)
 salathe06 июн. 2012 г., 19:31
Вы можете использоватьsetMaxDepth() метод наRecursiveIteratorIterator, чтобы ограничить глубину рекурсии: здесь вы, вероятно, хотите установить ее как1 (т. е. один подкаталог глубоко).
error_reporting(E_ALL);

function printTabs($level)
{
    echo "<br/><br/>";
    $l = 0;
    for (; $l < $level; $l++)
        echo ".";
}

function printFileCount($dirName, $init)
{
    $fileCount = 0;
    $st        = strrpos($dirName, "/");
    printTabs($init);
    echo substr($dirName, $st);

    $dHandle   = opendir($dirName);
    while (false !== ($subEntity = readdir($dHandle)))
    {
        if ($subEntity == "." || $subEntity == "..")
            continue;
        if (is_file($dirName . '/' . $subEntity))
        {
            $fileCount++;
        }
        else //if(is_dir($dirName.'/'.$subEntity))
        {
            printFileCount($dirName . '/' . $subEntity, $init + 1);
        }
    }
    printTabs($init);
    echo($fileCount . " files");

    return;
}

printFileCount("/var/www", 0);

все работает. Но выравнивание результатов плохо, логика работае

Показать / подсчитать общее и дополнительное количество каталогов

find . -type d -print | wc -l

Показать / посчитать общее количество файлов в основном и вспомогательном каталоге

find . -type f -print | wc -l

Показывать / считать только файлы из текущего каталога (без дополнительного каталога)

find . -maxdepth 1 -type f -print | wc -l

Показать / посчитать общее количество каталогов и файлов в текущем каталоге (без дополнительного каталога)

ls -1 | wc -l
 Eugen Mayer19 мая 2018 г., 12:20
Даун проголосовал, так как это ни в коем случае не отвечает на вопрос

Как я помню, opendir является производным от класса SplFileObject, который является классом RecursiveIterator, Traversable, Iterator, SeekableIterator, поэтому вам не нужны циклы while, если вы используете стандартную библиотеку PHP SPL для извлечения всего количества изображений даже на подкаталог.

Но я уже давно не использовал PHP, поэтому я мог ошибиться.

Ваш ответ на вопрос