web-dev-qa-db-ja.com

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%上昇する理由は何ですか?それを最適化するために何かできますか?または、フォルダーとそのサイズ内のフォルダーを確認する他の方法はありますか?

51
Mr Bosh

以下は他のソリューションです 他の場所で提供

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;
?>
38
Sampson
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;
}

ジャニス・チンタナが提案したのと同じアイデア。いくつかの修正:

  • $pathrealpath に変換します
  • パスが有効でフォルダーが存在する場合にのみ反復を実行します
  • .および..ファイルをスキップします
  • パフォーマンス向けに最適化
63
Alph.Dev

純粋なphpの例。

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

?>
27
vdbuilder

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;
} 
24
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;
} 
13
Alex Kashin

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);
    }
}
11
André Fiedler

このアプローチはより短く、より互換性があることがわかりました。 Mac OS Xバージョンの「du」は、何らかの理由で-b(または--bytes)オプションをサポートしていないため、より互換性のある-kオプションに固執します。

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

バイト単位で$ filesizeを返します。

6
Nate Lampton

この投稿にはすでに多くの回答がありますが、ディレクトリ内のすべてのファイルサイズの合計のみを(再帰的に)返すUNIXホスト用の別のオプションを追加する必要があります。

ジョナサンの答えを見ると、彼はduコマンドを使用しています。このコマンドはディレクトリの合計サイズを返しますが、純粋なPHPここで他の人が投稿したソリューションは、すべてのファイルサイズの合計を返します。大きな違い!

注目すべきこと

新しく作成されたディレクトリでduを実行すると、4K の代わりに 0。問題のディレクトリからファイルを削除した後、これはさらに混乱する可能性があり、duがその中のファイルのサイズの合計に対応しない合計ディレクトリサイズを報告します。どうして? Hermann Ingjaldssonが this post についてコメントしたように、コマンド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
halfpastfour.am

Johnathan SampsonのLinuxの例は、私にとってはあまりうまくいきませんでした。改善されたバージョンは次のとおりです。

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

スクリプトを最適化するためにできることはいくつかありますが、最大限の成功を収めると、CPUバインドではなくIOバインドになります。

  1. ループ外でrtrim($path, '/')を計算します。
  2. if ($t<>"." && $t<>"..")を外部テストにします-パスを統計する必要はありません
  3. ループごとに1回、rtrim($path, '/') . '/' . $tを計算します-2)内で1)を考慮します。
  4. 各呼び出しではなくexplode(' ','B KB MB GB TB PB');を1回計算しますか?
2
Douglas Leeder

PHPはディレクトリサイズを取得します(FTPアクセスを使用)

一生懸命働いた後、このコードは素晴らしい働きをします!!!!コミュニティと共有したい(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);

良いコード!フェルナンド

2
Fernando

ネイティブ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;
    }

注: この関数はディスク上のサイズではなくファイルサイズを返します

1
Accountant م

それは完全に正常に動作します。

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

オブジェクト指向アプローチ:

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

Johnathan SampsonのLinuxの例については、「du」関数の結果でintvalを実行しているときに注意してください。サイズが2GBを超える場合、2GBを表示し続けます。

置換:

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

by:

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

「du」関数は、スペースで区切られたサイズに続いてディレクトリ/ファイル名を返すと仮定します。

1
M J

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

ワンライナーソリューション。バイト単位の結果。

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

追加のボーナス:ファイルマスクを好きなものに変更し、特定のファイルのみをカウントすることができます(拡張子など)。

0
Steve Horvath

これは、使用しているプログラミング言語に関係なく、ディレクトリサイズを調べるための最も簡単なアルゴリズムです。 PHP固有の実装の場合。に移動: PHPでディレクトリサイズを計算する|アルゴリズムで説明|作業コード

0
Ayush Jain

メインディレクトリとその中のすべてのサブフォルダにアクセスするために調整されたコード。これにより、完全なディレクトリサイズが返されます。

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;
}
0
Ifeanyi Amadi