Get the Size of a Directory (Over 2GB) from a Linux, Unix, or Windows Server Using PHP

I had a project that required me to get a folder size using php. At first I thought this would be a snap. Unfortunately the only php solutions I found required iterating through directories and sub-directories, adding the size of each file one at a time. That just wouldn't work, it would take to much time. Then I found some information on using some *nix calls.


For those of us out there that are not Linux guru's, this function took me some time to put together. The problem I kept running into was that it never returned more than 2GB, even when I knew the directory was larger. The key to my problem was that in the popen('/usr/bin/du -sb '.$path, 'r') I was using -sb. This gave me the size in bytes, which is what I thought I wanted. While I wont pretend to know the ins and outs of a *nix system, I did find that if that same call is made using -ks I will get the size of the directory in KB. This got me past the 2GB boundary. You will find the function below:


function getNixDirSize($path) {
  $io = popen('/usr/bin/du -ks '.$path, 'r');
  $output = fgets ( $io, 4096);
  $result = preg_split('/\s/', $output);
  $size = $result[0]*1024;
  pclose($io);
  return $size;
}

That function worked for *nix based systems, but what about Windows? That one was actually a bit easier as there were some good examples out there.


function getWinDirSize($path) {
  $f = dirname(__FILE__);
  $obj = new COM ( 'scripting.filesystemobject' );
  if ( is_object ( $obj ) ){
    $ref = $obj->getfolder ( $path );
    $dir_size = $ref->size;
    $obj = null;
    return $dir_size;
  }
}

Now I just need to figure out if my website is running on a *nix or windows system. There are several ways to check what server is running, I decided to use PHP_OS. This is a php function that just finds what server php is running on.


if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
  //This is a server using Windows
  $output = format_bytes(getWinDirSize(dirname(__FILE__)));
} else {
  //This is a server not using Windows
  $output = format_bytes(getNixDirSize(dirname(__FILE__)));
}

I have one more function to add, format_bytes to format the size to something easy for humans to read. However, the windows function is giving me bytes, and the *nix is giving me KB. That's ok, because I added "*1024" to the end of "$size = $result[0]" in the *nix function, which changes KB to bytes before passing it to the format function below.


function format_bytes($a_bytes) {
  if ($a_bytes < 1024) {
    return $a_bytes .' B';
  } elseif ($a_bytes < 1048576) {
    return round($a_bytes / 1024, 2) .' KB';
  } elseif ($a_bytes < 1073741824) {
    return round($a_bytes / 1048576, 2) . ' MB';
  } elseif ($a_bytes < 1099511627776) {
    return round($a_bytes / 1073741824, 2) . ' GB';
  } elseif ($a_bytes < 1125899906842624) {
    return round($a_bytes / 1099511627776, 2) .' TB';
  }
}

I know these functions work up to 4.3GB on a Linux server and 4.7GB on a Windows server. I do not know if there is a size limit, but if the size is to large, then doing a space check every time a page is accessed would be prohibitive. Obviously this code can be cleaned up and put into a class, but that's for a later date.


Comments (0)



This thread has been closed from taking new comments.