Как получить размер каталога в PHP - PullRequest
51 голосов
/ 25 января 2009
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%, пока выполнение скрипта не закончится? Можно ли что-то сделать, чтобы оптимизировать это? или есть другой альтернативный способ проверить папку и папки внутри нее по размеру?

Ответы [ 18 ]

58 голосов
/ 28 января 2014
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;
}

Та же идея, что и Джанит Чинтана. С несколькими исправлениями:

  • Преобразует $path в realpath
  • Выполняет итерацию, только если путь верен и папка существует
  • Пропускает . и .. файлы
  • Оптимизирован для производительности
39 голосов
/ 25 января 2009

Ниже приведены другие решения , предлагаемые в других местах :

Если на хосте 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;
?>
27 голосов
/ 02 декабря 2011

Пример чистого 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];
}

?>
24 голосов
/ 17 августа 2013

размер каталога с использованием php размер файла и 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;
} 
13 голосов
/ 03 декабря 2014
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;
} 
11 голосов
/ 02 сентября 2013

Благодаря Джонатану Сэмпсону, Адаму Пирсу и Джанит Чинтана я проверил один из наиболее эффективных способов получения размера каталога. Должен работать на хостах 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);
    }
}
6 голосов
/ 23 апреля 2015

Несмотря на то, что ответов на этот пост уже много, я чувствую, что должен добавить еще один параметр для хостов Unix, который возвращает только сумму всех размеров файлов в каталоге (рекурсивно).

Если вы посмотрите на ответ Джонатана, он использует команду du. Эта команда вернет общий размер каталога, но чистые решения PHP, опубликованные другими здесь, вернут сумму всех размеров файлов. Большая разница!

На что обратить внимание

При запуске du во вновь созданном каталоге он может вернуть 4K вместо 0. Это может даже запутать после удаления файлов из рассматриваемого каталога, когда du сообщает об общем размере каталога, который не соответствует сумме размеров файлов в нем. Зачем? Команда du возвращает отчет, основанный на некоторых настройках файла, как Герман Ингялдссон прокомментировал этот пост .

Решение

Чтобы сформировать решение, которое ведет себя как некоторые из скриптов только для 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;
}
6 голосов
/ 27 июня 2012

Я нашел этот подход короче и более совместимым. Версия "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;

Возвращает размер файла $ в байтах.

6 голосов
/ 31 января 2012

Пример Джонатана Сэмпсона для Linux не сработал для меня. Вот улучшенная версия:

function getDirSize($path)
{
    $io = popen('/usr/bin/du -sb '.$path, 'r');
    $size = intval(fgets($io,80));
    pclose($io);
    return $size;
}
2 голосов
/ 14 августа 2014

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

Хороший код! Fernando

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...