How to get directory size in PHP

PhpFilesystems

Php Problem Overview


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

https://stackoverflow.com/questions/466140/php-disktotalspace#466268

Any idea why the processor usage shoot up too high or 100% till the script execution is finish ? Can anything be done to optimize it? or is there any other alternative way to check folder and folders inside it size?

Php Solutions


Solution 1 - Php

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

The same idea as Janith Chinthana suggested. With a few fixes:

  • Converts $path to realpath
  • Performs iteration only if path is valid and folder exists
  • Skips . and .. files
  • Optimized for performance

Solution 2 - Php

The following are other solutions offered elsewhere:

If on a Windows Host:

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

Else, if on a Linux Host:

<?
	$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;
?>

Solution 3 - Php

directory size using php filesize and RecursiveIteratorIterator.

This works with any platform which is having php 5 or higher version.

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

Solution 4 - Php

A pure php example.

<?php
    $units = explode(' ', 'B KB MB GB TB PB');
    $SIZE_LIMIT = 5368709120; // 5 GB
    $disk_used = foldersize("/webData/users/[email protected]");
    
    $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];
}

?>

Solution 5 - Php

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

Solution 6 - Php

Thanks to Jonathan Sampson, Adam Pierce and Janith Chinthana I did this one checking for most performant way to get the directory size. Should work on Windows and Linux Hosts.

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

Solution 7 - Php

I found this approach to be shorter and more compatible. The Mac OS X version of "du" doesn't support the -b (or --bytes) option for some reason, so this sticks to the more-compatible -k option.

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

Returns the $filesize in bytes.

Solution 8 - Php

Even though there are already many many answers to this post, I feel I have to add another option for unix hosts that only returns the sum of all file sizes in the directory (recursively).

If you look at Jonathan's answer he uses the du command. This command will return the total directory size but the pure PHP solutions posted by others here will return the sum of all file sizes. Big difference!

What to look out for

When running du on a newly created directory, it may return 4K instead of 0. This may even get more confusing after having deleted files from the directory in question, having du reporting a total directory size that does not correspond to the sum of the sizes of the files within it. Why? The command du returns a report based on some file settings, as Hermann Ingjaldsson commented on this post.

The solution

To form a solution that behaves like some of the PHP-only scripts posted here, you can use ls command and pipe it to awk like this:

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

As a PHP function you could use something like this:

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

Solution 9 - Php

Johnathan Sampson's Linux example didn't work so good for me. Here's an improved version:

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

Solution 10 - Php

It works perfectly fine .

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

Solution 11 - Php

There are several things you could do to optimise the script - but maximum success would make it IO-bound rather than CPU-bound:

  1. Calculate rtrim($path, '/') outside the loop.
  2. make if ($t<>"." && $t<>"..") the outer test - it doesn't need to stat the path
  3. Calculate rtrim($path, '/') . '/' . $t once per loop - inside 2) and taking 1) into account.
  4. Calculate explode(' ','B KB MB GB TB PB'); once rather than each call?

Solution 12 - Php

PHP get directory size (with FTP access)

After hard work, this code works great!!!! and I want to share with the community (by 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);

Good code! Fernando

Solution 13 - Php

Object Oriented Approach :

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

Fast and Furious Approach :

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

Solution 14 - Php

Code adjusted to access main directory and all sub folders within it. This would return the full directory size.

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

Solution 15 - Php

if you are hosted on Linux:

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

It's better than foreach

Solution 16 - Php

Regarding Johnathan Sampson's Linux example, watch out when you are doing an intval on the outcome of the "du" function, if the size is >2GB, it will keep showing 2GB.

Replace:

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

by:

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

supposed your "du" function returns the size separated with space followed by the directory/file name.

Solution 17 - Php

Just another function using native php functions.

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

NOTE: this function returns the files sizes, NOT the size on disk

Solution 18 - Php

Evolved from Nate Haugs answer I created a short function for my project:

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

Solution 19 - Php

A one-liner solution. Result in bytes.

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

Added bonus: you can simply change the file mask to whatever you like, and count only certain files (eg by extension).

Solution 20 - Php

This is the simplest possible algorithm to find out directory size irrespective of the programming language you are using. For PHP specific implementation. go to: Calculate Directory Size in PHP | Explained with Algorithm | Working Code

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMr BoshView Question on Stackoverflow
Solution 1 - PhpSlavaView Answer on Stackoverflow
Solution 2 - PhpSampsonView Answer on Stackoverflow
Solution 3 - PhpJanith ChinthanaView Answer on Stackoverflow
Solution 4 - PhpvdbuilderView Answer on Stackoverflow
Solution 5 - PhpAlex KashinView Answer on Stackoverflow
Solution 6 - PhpAndré FiedlerView Answer on Stackoverflow
Solution 7 - PhpNate LamptonView Answer on Stackoverflow
Solution 8 - Phphalfpastfour.amView Answer on Stackoverflow
Solution 9 - PhpAdam PierceView Answer on Stackoverflow
Solution 10 - PhpakshaypjoshiView Answer on Stackoverflow
Solution 11 - PhpDouglas LeederView Answer on Stackoverflow
Solution 12 - PhpFernandoView Answer on Stackoverflow
Solution 13 - PhphugsbrugsView Answer on Stackoverflow
Solution 14 - PhpIfeanyi AmadiView Answer on Stackoverflow
Solution 15 - PhpfarzaView Answer on Stackoverflow
Solution 16 - PhpM JView Answer on Stackoverflow
Solution 17 - PhpAccountant مView Answer on Stackoverflow
Solution 18 - Phpmaxpower9000View Answer on Stackoverflow
Solution 19 - PhpSteve HorvathView Answer on Stackoverflow
Solution 20 - PhpAyush JainView Answer on Stackoverflow