1

我有一个目录,其中包含年份的子目录(例如 2009),并且在这些子目录中包含月份的子目录(例如 02)

我需要计算每个月文件夹中的文件总数,以及每个文件夹的文件总大小,并输出两个总数(总大小和文件总数)以及年份和月份文件夹名称。

例子:

  • 05/2009 - 512MB(12 个文件)

  • 06/2009 - 45KB(21 个文件)

  • 07/2009 - 6MB(8 个文件)

  • 01/2011 - 54MB(2 个文件)

  • 04/2011 - 652MB(55 个文件)

...

我创建了以下函数来计算目录的总大小和文件。如何调整它以适应上述多子文件夹列表?

function foldersize($path) {
    $total_size = 0;
    $total_files = 0;

    $files = scandir($path);

    foreach($files as $file) {
        if ($t<>"." && $t <> "..") {
            if (is_dir($path.'/'.$file)) {
                $size = foldersize($path.'/'.$file);
                $total_files++;
                $total_size += $size;
            }
            else {
                $size = filesize($path.'/'.$file);
                $total_files++;
                $total_size += $size;
            }
        }   
    }

    return $total_size.' | '.$total_files;
}
4

2 回答 2

1

您应该使用RecursiveDirectoryIterator递归地遍历子目录。

$_recursiveIterator = new RecursiveDirectoryIterator(
    $path, FilesystemIterator::SKIP_DOTS);
$iterator = new RecursiveIteratorIterator(
    $_recursiveIterator, RecursiveIteratorIterator::SELF_FIRST);
foreach($iterator as $subdirPath => $subdirInfo) {
    if ($subdirInfo->isDir()) {
        echo $subdirPath . ' ' . foldersize($subdirPath);
    }
}

这里发生的事情有点难以理解,并且 SPL 迭代器没有很好地记录,所以我将尝试解释:

  • 迭代器是实现特殊接口的对象,因此它们可以在foreach循环中使用
  • RecursiveDirectoryIterator是文件系统的递归迭代器。递归迭代器是一种特殊类型的迭代器,它在每次迭代中自己产生一个迭代器。它们可用于嵌套数据结构。
  • SKIP_DOTS告诉它忽略.and..条目
  • RecursiveIteratorIterator用于“展平”递归迭代器。它通过递归迭代器并在单个循环中产生所有后续条目。
  • SELF_FIRST表示父母先于子女(即 2009 年 2009/01 年之前)
  • 在循环中,关键$subdirPath是每个项目的路径和对象的值$subdirInfoSplFileInfo实际上,它是 RecursiveDirectoryIterator 本身,它最终从 SplFileInfo 扩展 - 但此时这并不重要)
  • isDir() 检查当前项是否为目录

下一步将重构您的foldersize()函数以使用迭代器。一次迭代所有文件和大小计算可能是明智的。编辑:查看 Mike Brant 的答案以获得这样的解决方案,上面的解释也适用于此。

于 2013-01-21T23:34:25.987 回答
1

您应该查看SPL 中提供的recursiveDirectoryIterator和类。recursiveIteratorIterator这应该可以很好地满足您的需求。

http://php.net/manual/en/class.recursivedirectoryiterator.php http://php.net/manual/en/class.recursiveiteratoriterator.php

示例用法:

$path = realpath('/path/to/directory');
$total_files = 0;
$total_filesize = 0;
$dir_files = 0;
$dir_filesize = 0;

$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS), RecursiveIteratorIterator::SELF_FIRST);
$first_dir = true;
foreach($iterator as $path => $object){
    if ($path->isDir()) {
        // echo out information from last directory
        if (false === $first_dir) {
            echo "Number of Files in Directory: " . $dir_files . "\nTotal File Size of Directory: " . $dir_filesize . " bytes\n\n";
            // reset directory counters
            $dir_files = 0;
            $dir_filesize = 0;
        }
        // start new directory output
        echo $path->getPathname() . "\n";
    } else if ($path->isFile()) {
        $total_filesize += $path->getSize();
        $dir_filesize += $path->getSize();
        $total_files++;
        $dir_files++;
    }
}

echo "\nTotal Files: " . $total_files . "\nTotal File Size: " . $total_filesize . " bytes";
于 2013-01-21T23:15:48.763 回答