如何在 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% 直到脚本执行完成吗?我们能做些什么来优化它吗?或者还有其他方法来检查文件夹和文件夹内的大小?

120057 次浏览

您可以做几件事来优化脚本——但是最大限度的成功将使它受 IO 而不是 CPU 的约束:

  1. 在循环外计算 rtrim($path, '/')
  2. 使 if ($t<>"." && $t<>"..")成为外部测试-它不需要统计路径
  3. 每个循环计算一次 rtrim($path, '/') . '/' . $t-内部2)和考虑1)。
  4. 计算一次 explode(' ','B KB MB GB TB PB');而不是每次呼叫?

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

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

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


?>

Johnathan Sampson 的 Linux 示例对我来说不太好用,下面是一个改进版本:

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

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

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

返回以字节为单位的 $filesize。

根据 Nate Haugs 的回答,我为我的项目创建了一个简短的函数:

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

目录大小使用 php文件大小递归迭代器

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

/**
* Get the directory size
* @param  string $directory
* @return integer
*/
function dirSize($directory) {
$size = 0;
foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory)) as $file){
$size+=$file->getSize();
}
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);
}
}
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转换为 真实路径
  • 仅当路径有效且文件夹存在时才执行迭代
  • 跳过 ...文件
  • 性能优化

PHP 获取目录大小(使用 FTP 访问)

经过艰苦的工作,这个代码工作的很好! ! ! ! 我想与社区分享(由 Mundisys)

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);

好密码! 费尔南多

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

尽管这篇文章已经有很多答案了,我还是觉得必须为 unix host 添加另一个选项,它只返回目录中所有文件大小的总和(递归)。

如果你看乔纳森的答案,他使用 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}'

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

关于 Johnathan Sampson 的 Linux 示例,当对“ du”函数的结果执行 intval 时,请注意,如果大小 > 2GB,它将继续显示2GB。

替换:

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

作者:

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

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

面向对象方法:

/**
* 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;
}

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

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

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

一行程序的解决方案。结果以字节为单位。

$size=array_sum(array_map('filesize', glob("{$dir}/*.*")));

附加的好处: 你可以简单地改变文件掩码到任何你喜欢的,并且只计算某些文件(例如通过扩展)。

调整代码以访问主目录和其中的所有子文件夹。这将返回完整的目录大小。

function get_dir_size($directory){
$size = 0;
$files= glob($directory.'/*');
foreach($files as $path){
is_file($path) && $size += filesize($path);


if (is_dir($path))
{
$size += get_dir_size($path);
}
}
return $size;
}

完全没问题。

     public static function folderSize($dir)
{
$size = 0;


foreach (glob(rtrim($dir, '/') . '/*', GLOB_NOSORT) as $each) {
$func_name = __FUNCTION__;
$size += is_file($each) ? filesize($each) : static::$func_name($each);
}


return $size;
}

无论使用何种编程语言,这都是求出目录大小的最简单的可能算法。 用于 PHP 特定的实现。访问: http://fullstackgeek.blogspot.com/2019/08/Calcul- Directory-Size-in-PHP.html rel = “ nofollow noReferrer”> 用 PHP 计算目录大小 | 用算法解释 | 工作代码

如果你在 Linux 上托管:

passthru('du -h -s ' . $DIRECTORY_PATH)

总比 Foreach 好