如何在PHP中获取目录大小

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>'; } 

php的disk_total_space

任何想法为什么处理器使用率太高或100%,直到脚本执行完成? 可以做任何事情来优化它吗? 或者有没有其他的方法来检查文件夹和文件夹里面的大小?

以下是在别处提供的其他解决scheme:

如果在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'; } ?> 

否则,如果在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; ?> 
 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; } 

Janith Chinthana提出了同样的想法。 有一些修正:

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

一个纯粹的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]; } ?> 

目录大小使用php filesize和RecursiveIteratorIterator 。

这适用于任何有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; } 
 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; } 

感谢乔纳森·桑普森(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); } } 

Johnathan Sampson的Linux例子并不适合我。 这是一个改进的版本:

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

我发现这种方法更短,更兼容。 由于某些原因,“du”的Mac OS X版本不支持-b(或–bytes)选项,所以这将坚持更兼容的-k选项。

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

以字节为单位返回$ filesize。

即使已经有很多这个post的答案,我感到我必须为unix主机添加另一个选项,只返回目录中所有文件大小的总和(recursion)。

如果你看乔纳森的答案,他使用du命令。 此命令将返回总目录大小,但其他人发布的纯PHP解决scheme将返回所有文件大小的总和。 巨大差距!

什么要注意

在新创build的目录上运行du时,可能会返回4K而不是0 。 在从目录中删除文件之后,这可能会变得更加令人困惑,因为报告的总目录大小与其中文件大小的总和不相符。 为什么? du命令根据一些文件设置返回报告,正如Hermann Ingjaldsson在这篇文章中评论的那样 。

解决scheme

为了形成一个类似于这里发布的一些PHP脚本的解决scheme,你可以使用ls命令来pipe理awk像这样:

 ls -ltrR /path/to/dir |awk '{print \$5}'|awk 'BEGIN{sum=0} {sum=sum+\$1} END {print sum}' 

作为一个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; } 

有几件事情可以用来优化脚本 – 但最大的成功将使得它的IO绑定,而不是CPU绑定:

  1. 计算循环外部的rtrim($path, '/')
  2. make if ($t<>"." && $t<>"..")外部testing – 它不需要统计path
  3. 计算rtrim($path, '/') . '/' . $t rtrim($path, '/') . '/' . $t rtrim($path, '/') . '/' . $t每个循环一次 – 内部2)并考虑到1)。
  4. 计算explode(' ','B KB MB GB TB PB'); 一次而不是每次打电话?

PHP获取目录大小(通过FTP访问)

经过努力,这个代码很好! 我想和社区分享(由MundialSYS提供)

 function dirFTPSize($ftpStream, $dir) { $size = 0; $files = ftp_nlist($ftpStream, $dir); foreach ($files as $remoteFile) { if(preg_match('/.*\/\.\.$/', $remoteFile) || preg_match('/.*\/\.$/', $remoteFile)){ continue; } $sizeTemp = ftp_size($ftpStream, $remoteFile); if ($sizeTemp > 0) { $size += $sizeTemp; }elseif($sizeTemp == -1){//directorio $size += dirFTPSize($ftpStream, $remoteFile); } } return $size; } $hostname = '127.0.0.1'; // or 'ftp.domain.com' $username = 'username'; $password = 'password'; $startdir = '/public_html'; // absolute path $files = array(); $ftpStream = ftp_connect($hostname); $login = ftp_login($ftpStream, $username, $password); if (!$ftpStream) { echo 'Wrong server!'; exit; } else if (!$login) { echo 'Wrong username/password!'; exit; } else { $size = dirFTPSize($ftpStream, $startdir); } echo number_format(($size / 1024 / 1024), 2, '.', '') . ' MB'; ftp_close($ftpStream); 

好的代码! 费尔南多

关于Johnathan Sampson的Linux例子,当你对“du”函数的结果进行一个intval时,要小心,如果size大于2GB,它将继续显示2GB。

更换:

 $totalSize = intval(fgets($io, 80)); 

通过:

 strtok(fgets($io, 80), " "); 

假设你的“du”函数返回由空格分隔的大小,后跟目录/文件名。

只是另一个使用本机phpfunction的函数。

 function dirSize($dir) { $dirSize = 0; if(!is_dir($dir)){return false;}; $files = scandir($dir);if(!$files){return false;} $files = array_diff($files, array('.','..')); foreach ($files as $file) { if(is_dir("$dir/$file")){ $dirSize += dirSize("$dir/$file"); }else{ $dirSize += filesize("$dir/$file"); } } return $dirSize; } 

注: 此函数返回文件大小,而不是磁盘上的大小

从内特豪格斯的演变回答我创build了一个简短的函数为我的项目:

 function uf_getDirSize($dir, $unit = 'm') { $dir = trim($dir, '/'); if (!is_dir($dir)) { trigger_error("{$dir} not a folder/dir/path.", E_USER_WARNING); return false; } if (!function_exists('exec')) { trigger_error('The function exec() is not available.', E_USER_WARNING); return false; } $output = exec('du -sb ' . $dir); $filesize = (int) trim(str_replace($dir, '', $output)); switch ($unit) { case 'g': $filesize = number_format($filesize / 1073741824, 3); break; // giga case 'm': $filesize = number_format($filesize / 1048576, 1); break; // mega case 'k': $filesize = number_format($filesize / 1024, 0); break; // kilo case 'b': $filesize = number_format($filesize, 0); break; // byte } return ($filesize + 0); } 

面向对象的方法:

 /** * Returns a directory size * * @param string $directory * * @return int $size directory size in bytes * */ function dir_size($directory) { $size = 0; foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory)) as $file) { $size += $file->getSize(); } return $size; } 

快速和激情的方法:

 function dir_size2($dir) { $line = exec('du -sh ' . $dir); $line = trim(str_replace($dir, '', $line)); return $line; }