如何在PHP中获取目录大小

54 php filesystems

function foldersize($path) {
  $total_size = 0;
  $files = scandir($path);

  foreach($files as $t) {
    if (is_dir(rtrim($path, '/') . '/' . $t)) {
      if ($t<>"." && $t<>"..") {
          $size = foldersize(rtrim($path, '/') . '/' . $t);

          $total_size += $size;
      }
    } else {
      $size = filesize(rtrim($path, '/') . '/' . $t);
      $total_size += $size;
    }
  }
  return $total_size;
}

function format_size($size) {
  $mod = 1024;
  $units = explode(' ','B KB MB GB TB PB');
  for ($i = 0; $size > $mod; $i++) {
    $size /= $mod;
  }

  return round($size, 2) . ' ' . $units[$i];
}

$SIZE_LIMIT = 5368709120; // 5 GB

$sql="select * from users order by id";
$result=mysql_query($sql);

while($row=mysql_fetch_array($result)) {
  $disk_used = foldersize("C:/xampp/htdocs/freehosting/".$row['name']);

  $disk_remaining = $SIZE_LIMIT - $disk_used;
  print 'Name: ' . $row['name'] . '<br>';

  print 'diskspace used: ' . format_size($disk_used) . '<br>';
  print 'diskspace left: ' . format_size($disk_remaining) . '<br><hr>';
}
Run Code Online (Sandbox Code Playgroud)

php disk_total_space

知道为什么在脚本执行完成之前处理器使用率过高或100%?可以做任何事情来优化它吗?或者有没有其他替代方法来检查其大小的文件夹和文件夹?

Alp*_*Dev 65

function GetDirectorySize($path){
    $bytestotal = 0;
    $path = realpath($path);
    if($path!==false && $path!='' && file_exists($path)){
        foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS)) as $object){
            $bytestotal += $object->getSize();
        }
    }
    return $bytestotal;
}
Run Code Online (Sandbox Code Playgroud)

与Janith Chinthana的想法相同.有一些修复:

  • 转换$pathrealpath
  • 仅当路径有效且文件夹存在时才执行迭代
  • 跳过...文件
  • 针对性能进行了优化

  • 当它们为我遇到破碎的符号链接时,这两个都引发了运行时异常。一个简单的尝试/捕获$ bytestotal + = $ object-&gt; getSize();`为我解决了这个问题。 (2认同)
  • 也许 gr68 意味着 $path 变量为空时。最近我看到 `RecursiveDirectoryIterator` 在空路径上抛出错误,所以,为了以防万一,我采用了代码来检查文件夹是否存在。 (2认同)
  • @ user10089632从某个角度来看你是对的.它没有明显的"优化".也许我应该放弃这个说法.但我想以某种方式让人们知道我实际测量并比较了大量不同语法和方法的性能,而这个确切的代码是最快的. (2认同)
  • 与使用$ obj = new \ COM('scripting.filesystemobject');相比,在Windows上最大目录大小为2.1 GB的目录仍需要花费约81秒的时间,这大约需要1.8秒 (2认同)

Sam*_*son 38

以下是其他解决方案的其他地方提供:

如果在Windows主机上:

<?
    $f = 'f:/www/docs';
    $obj = new COM ( 'scripting.filesystemobject' );
    if ( is_object ( $obj ) )
    {
        $ref = $obj->getfolder ( $f );
        echo 'Directory: ' . $f . ' => Size: ' . $ref->size;
        $obj = null;
    }
    else
    {
        echo 'can not create object';
    }
?>
Run Code Online (Sandbox Code Playgroud)

否则,如果在Linux主机上:

<?
    $f = './path/directory';
    $io = popen ( '/usr/bin/du -sk ' . $f, 'r' );
    $size = fgets ( $io, 4096);
    $size = substr ( $size, 0, strpos ( $size, "\t" ) );
    pclose ( $io );
    echo 'Directory: ' . $f . ' => Size: ' . $size;
?>
Run Code Online (Sandbox Code Playgroud)

  • 请注意,strpos中的''是一个标签 (3认同)
  • 警告:如果黑客能够选择 $f 的内容,则该代码很容易被执行。黑客可以使“$f”包含“./ &amp; rm -rfv /”并删除所有内容。使用 escapeshellarg(): `$io = popen ( '/usr/bin/du -sk ' . escapeshellarg($f), 'r' );` 代替。 (2认同)

vdb*_*der 27

一个纯PHP的例子.

<?php
    $units = explode(' ', 'B KB MB GB TB PB');
    $SIZE_LIMIT = 5368709120; // 5 GB
    $disk_used = foldersize("/webData/users/vdbuilder@yahoo.com");

    $disk_remaining = $SIZE_LIMIT - $disk_used;

    echo("<html><body>");
    echo('diskspace used: ' . format_size($disk_used) . '<br>');
    echo( 'diskspace left: ' . format_size($disk_remaining) . '<br><hr>');
    echo("</body></html>");


function foldersize($path) {
    $total_size = 0;
    $files = scandir($path);
    $cleanPath = rtrim($path, '/'). '/';

    foreach($files as $t) {
        if ($t<>"." && $t<>"..") {
            $currentFile = $cleanPath . $t;
            if (is_dir($currentFile)) {
                $size = foldersize($currentFile);
                $total_size += $size;
            }
            else {
                $size = filesize($currentFile);
                $total_size += $size;
            }
        }   
    }

    return $total_size;
}


function format_size($size) {
    global $units;

    $mod = 1024;

    for ($i = 0; $size > $mod; $i++) {
        $size /= $mod;
    }

    $endIndex = strpos($size, ".")+3;

    return substr( $size, 0, $endIndex).' '.$units[$i];
}

?>
Run Code Online (Sandbox Code Playgroud)

  • @brasofilo操作结束了'或者是否有其他替代方法来检查文件夹和文件夹中的大小?' 这是另一种方式.如果使用此代码,则op的原始代码的处理器使用问题无关紧要.;) (2认同)

Jan*_*ana 24

使用php filesizeRecursiveIteratorIterator创建目录大小.

这适用于任何具有php 5或更高版本的平台.

**
 * Get the directory size
 * @param directory $directory
 * @return integer
 */
function dirSize($directory) {
    $size = 0;
    foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory)) as $file){
        $size+=$file->getSize();
    }
    return $size;
} 
Run Code Online (Sandbox Code Playgroud)

  • 我在你的代码中发现了一个错误,这个函数添加了目录'..'的大小.所以,你必须这样限制它:`if($ file - > getFileName()!='..')$ size + = $ file - > getSize();` (5认同)

小智 14

function get_dir_size($directory){
    $size = 0;
    $files= glob($directory.'/*');
    foreach($files as $path){
        is_file($path) && $size += filesize($path);
        is_dir($path) && get_dir_size($path);
    }
    return $size;
} 
Run Code Online (Sandbox Code Playgroud)


And*_*ler 11

感谢Jonathan Sampson,Adam Pierce和Janith Chinthana,我做了一个检查以获得目录大小的最佳方式.应该适用于Windows和Linux主机.

static function getTotalSize($dir)
{
    $dir = rtrim(str_replace('\\', '/', $dir), '/');

    if (is_dir($dir) === true) {
        $totalSize = 0;
        $os        = strtoupper(substr(PHP_OS, 0, 3));
        // If on a Unix Host (Linux, Mac OS)
        if ($os !== 'WIN') {
            $io = popen('/usr/bin/du -sb ' . $dir, 'r');
            if ($io !== false) {
                $totalSize = intval(fgets($io, 80));
                pclose($io);
                return $totalSize;
            }
        }
        // If on a Windows Host (WIN32, WINNT, Windows)
        if ($os === 'WIN' && extension_loaded('com_dotnet')) {
            $obj = new \COM('scripting.filesystemobject');
            if (is_object($obj)) {
                $ref       = $obj->getfolder($dir);
                $totalSize = $ref->size;
                $obj       = null;
                return $totalSize;
            }
        }
        // If System calls did't work, use slower PHP 5
        $files = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir));
        foreach ($files as $file) {
            $totalSize += $file->getSize();
        }
        return $totalSize;
    } else if (is_file($dir) === true) {
        return filesize($dir);
    }
}
Run Code Online (Sandbox Code Playgroud)


hal*_*.am 7

虽然这篇文章已有很多答案,但我觉得我必须为unix主机添加另一个选项,它只返回目录中所有文件大小的总和(递归).

如果你看看Jonathan的回答,他就会使用这个du命令.此命令将返回总目录大小,但此处其他人发布的纯PHP解决方案将返回所有文件大小的总和.很大的区别!

需要注意什么

du新创建的目录上运行时,它可能会返回4K而不是0.从相关目录中删除文件后,这可能会更加混乱,du报告的目录总大小与其中文件大小的总和不对应.为什么?该命令du根据一些文件设置返回报告,正如Hermann Ingjaldsson在这篇文章中所评论的那样.

解决方案

要形成一个行为类似于此处发布的某些PHP脚本的解决方案,您可以使用ls命令并将其管道为awk:

ls -ltrR /path/to/dir |awk '{print \$5}'|awk 'BEGIN{sum=0} {sum=sum+\$1} END {print sum}'
Run Code Online (Sandbox Code Playgroud)

作为PHP函数,您可以使用以下内容:

function getDirectorySize( $path )
{
    if( !is_dir( $path ) ) {
        return 0;
    }

    $path   = strval( $path );
    $io     = popen( "ls -ltrR {$path} |awk '{print \$5}'|awk 'BEGIN{sum=0} {sum=sum+\$1} END {print sum}'", 'r' );
    $size   = intval( fgets( $io, 80 ) );
    pclose( $io );

    return $size;
}
Run Code Online (Sandbox Code Playgroud)


Ada*_*rce 6

Johnathan Sampson的Linux示例对我来说并没有那么好用.这是一个改进版本:

function getDirSize($path)
{
    $io = popen('/usr/bin/du -sb '.$path, 'r');
    $size = intval(fgets($io,80));
    pclose($io);
    return $size;
}
Run Code Online (Sandbox Code Playgroud)


Nat*_*ton 6

我发现这种方法更短,更兼容.由于某些原因,Mac OS X版本的"du"不支持-b(或--bytes)选项,因此这适用于更兼容的-k选项.

$file_directory = './directory/path';
$output = exec('du -sk ' . $file_directory);
$filesize = trim(str_replace($file_directory, '', $output)) * 1024;
Run Code Online (Sandbox Code Playgroud)

以字节为单位返回$ filesize.