web-dev-qa-db-de.com

Wie bekomme ich die Verzeichnisgröße? 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

Gibt es eine Idee, warum die Prozessorauslastung zu hoch oder zu 100% hoch ist, bis die Skriptausführung abgeschlossen ist? Kann man etwas tun, um es zu optimieren? oder gibt es eine andere alternative Möglichkeit, Ordner und Ordner innerhalb der Größe zu überprüfen?

48
Mr Bosh

Im Folgenden sind weitere Lösungen an anderer Stelle angeboten :

Wenn auf einem 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';
    }
?>

Ansonsten, wenn auf einem 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;
?>
39
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;
}

Dieselbe Idee wie Janith Chinthana. Mit ein paar Korrekturen:

  • Konvertiert $path in realpath
  • Führt die Iteration nur aus, wenn der Pfad gültig ist und ein Ordner vorhanden ist
  • Überspringt .- und ..-Dateien
  • Für Leistung optimiert
56
Alph.Dev

Ein reines PHP-Beispiel.

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

verzeichnisgröße mit php filesize und RecursiveIteratorIterator

Dies funktioniert mit jeder Plattform, die PHP-Version 5 oder höher hat.

**
 * 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

Dank Jonathan Sampson, Adam Pierce und Janith Chinthana überprüfte ich den performantesten Weg, um die Verzeichnisgröße zu ermitteln. Sollte auf Windows- und Linux-Hosts funktionieren.

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

Ich fand diesen Ansatz kürzer und kompatibler. Die Mac OS X-Version von "du" unterstützt aus irgendeinem Grund die Option -b (oder --bytes) nicht. Daher bleibt die Option -k mit mehr kompatibel.

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

Gibt die $ filesize in Bytes zurück.

6
Nate Lampton

Johnathan Sampsons Linux-Beispiel hat für mich nicht so gut funktioniert. Hier ist eine verbesserte Version:

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

Obwohl es bereits viele Antworten zu diesem Beitrag gibt, denke ich, dass ich eine weitere Option für Unix-Hosts hinzufügen muss, die nur die Summe aller Dateigrößen im Verzeichnis (rekursiv) zurückgibt.

Wenn Sie sich Jonathans Antwort ansehen, verwendet er den Befehl du. Dieser Befehl gibt die gesamte Verzeichnisgröße zurück, aber die reinen PHP -Lösungen, die von anderen hier veröffentlicht werden, geben die Summe aller Dateigrößen zurück. Großer Unterschied!

Worauf muss ich achten?

Wenn Sie du in einem neu erstellten Verzeichnis ausführen, kann 4K anstelle von 0 zurückgegeben werden. Dies kann sogar verwirrender werden, wenn Sie Dateien aus dem betreffenden Verzeichnis gelöscht haben und du eine Gesamtverzeichnisgröße meldet, die nicht der Summe der Größen der darin enthaltenen Dateien entspricht. Warum? Der Befehl du gibt einen Bericht zurück, der auf einigen Dateieinstellungen basiert, wie Hermann Ingjaldsson diesen Beitrag kommentierte.

Die Lösung

Um eine Lösung zu bilden, die sich wie einige der hier veröffentlichten PHP-Skripte verhält, können Sie den Befehl ls verwenden und ihn wie folgt an awk weiterleiten:

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

Als PHP -Funktion können Sie etwa Folgendes verwenden:

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;
}
5
halfpastfour.am

Es gibt verschiedene Möglichkeiten, das Skript zu optimieren - aber der maximale Erfolg würde dazu führen, dass es IO-gebunden und nicht CPU-gebunden ist:

  1. rtrim($path, '/') außerhalb der Schleife berechnen.
  2. if ($t<>"." && $t<>"..") zum äußeren Test machen - der Pfad muss nicht angegeben werden
  3. Berechnen Sie rtrim($path, '/') . '/' . $t einmal pro Schleife - in 2) und unter Berücksichtigung von 1).
  4. explode(' ','B KB MB GB TB PB'); einmal pro Anruf berechnen?
2
Douglas Leeder

PHP get Verzeichnisgröße (mit FTP-Zugriff)

Nach harter Arbeit funktioniert dieser Code hervorragend !!!! und ich möchte mit der Community teilen (von 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);

Guter Code! Fernando

2
Fernando

Nur eine weitere Funktion, die native PHP-Funktionen verwendet.

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

HINWEIS: Diese Funktion gibt die Dateigrößen zurück, NICHT die Größe auf der Festplatte.

1
Accountant م

Objektorientierter Ansatz: 

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

Schneller und wütender Ansatz:

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

In Bezug auf Johnathan Sampsons Linux-Beispiel sollten Sie aufpassen, wenn Sie einen Intval über das Ergebnis der "du" -Funktion machen. Wenn die Größe> 2 GB ist, werden 2 GB angezeigt.

Ersetzen Sie:  

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

durch:

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

angenommen, Ihre "du" -Funktion gibt die Größe mit Leerzeichen gefolgt vom Verzeichnis-/Dateinamen zurück.

1
M J

Nach der Antwort von Nate Haugs entwickelte ich eine kurze Funktion für mein Projekt:

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

Es funktioniert perfekt.

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

Eine Einliner-Lösung. Ergebnis in Bytes.

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

Zusätzlicher Bonus: Sie können einfach die Dateimaske beliebig ändern und nur bestimmte Dateien zählen (zB nach Erweiterung).

0
Steve Horvath

Dies ist der einfachste mögliche Algorithmus zum Ermitteln der Verzeichnisgröße, unabhängig von der verwendeten Programmiersprache. Für PHP spezifische Implementierung. Gehen Sie zu: Berechnen Sie die Verzeichnisgröße in PHP | Erklärt mit Algorithmus | Arbeitscode

0
Ayush Jain

Code für den Zugriff auf das Hauptverzeichnis und alle darin enthaltenen Unterordner angepasst. Dies würde die volle Verzeichnisgröße zurückgeben.

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