php 如何在PHP中获取目录大小
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/478121/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get directory size in PHP
提问by Alph.Dev
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>';
}
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?
知道为什么在脚本执行完成之前处理器使用率过高或达到 100% 吗?有什么办法可以优化它吗?或者有没有其他替代方法来检查文件夹和文件夹的大小?
采纳答案by Sampson
The following are other solutions offered elsewhere:
以下是其他地方提供的其他解决方案:
If on a Windows Host:
如果在 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';
}
?>
Else, if on a Linux Host:
否则,如果在 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;
?>
回答by Alph.Dev
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:
与 Janith Chinthana 建议的想法相同。有一些修复:
- Converts
$pathto realpath - Performs iteration only if path is valid and folder exists
- Skips
.and..files - Optimized for performance
- 转换
$path为实路径 - 仅当路径有效且文件夹存在时才执行迭代
- 跳过
.和..文件 - 性能优化
回答by vdbuilder
A pure php example.
一个纯 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];
}
?>
回答by Janith Chinthana
directory size using php filesizeand RecursiveIteratorIterator.
目录大小使用 php filesize和RecursiveIteratorIterator。
This works with any platform which is having php 5 or higher version.
这适用于任何具有 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;
}
回答by Alex Kashin
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;
}
回答by André Fiedler
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.
感谢 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);
}
}
回答by halfpastfour.am
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).
尽管这篇文章已经有很多答案,但我觉得我必须为 unix 主机添加另一个选项,它只返回目录中所有文件大小的总和(递归)。
If you look at Jonathan's answer he uses the ducommand. 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!
如果您查看 Jonathan 的回答,他会使用该du命令。此命令将返回总目录大小,但其他人在此处发布的纯 PHP 解决方案将返回所有文件大小的总和。巨大差距!
What to look out for
需要注意什么
When running duon a newly created directory, it may return 4Kinstead of 0. This may even get more confusing after having deleted files from the directory in question, having dureporting a total directory size that does not correspond to the sum of the sizes of the files within it. Why? The command dureturns a report based on some file settings, as Hermann Ingjaldsson commented on this post.
在du新创建的目录上运行时,它可能会返回4K而不是0. 从相关目录中删除文件后,这甚至可能会变得更加混乱,因为du报告的总目录大小与其中文件大小的总和不符。为什么?该命令du返回基于某些文件设置的报告,正如 Hermann Ingjaldsson 在这篇文章中评论的那样。
The solution
解决方案
To form a solution that behaves like some of the PHP-only scripts posted here, you can use lscommand and pipe it to awklike this:
要形成一个解决方案,其行为类似于此处发布的某些仅限 PHP 的脚本,您可以使用lscommand 并将其管道化为awk如下所示:
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:
作为一个 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;
}
回答by Adam Pierce
Johnathan Sampson's Linux example didn't work so good for me. Here's an improved version:
Johnathan Sampson 的 Linux 示例对我来说效果不佳。这是一个改进版本:
function getDirSize($path)
{
$io = popen('/usr/bin/du -sb '.$path, 'r');
$size = intval(fgets($io,80));
pclose($io);
return $size;
}
回答by Nate Lampton
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.
我发现这种方法更短,更兼容。由于某种原因,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;
Returns the $filesize in bytes.
以字节为单位返回 $filesize。
回答by Douglas Leeder
There are several things you could do to optimise the script - but maximum success would make it IO-bound rather than CPU-bound:
您可以做几件事来优化脚本 - 但最大的成功是让它受 IO 限制而不是受 CPU 限制:
- Calculate
rtrim($path, '/')outside the loop. - make
if ($t<>"." && $t<>"..")the outer test - it doesn't need to stat the path - Calculate
rtrim($path, '/') . '/' . $tonce per loop - inside 2) and taking 1) into account. - Calculate
explode(' ','B KB MB GB TB PB');once rather than each call?
rtrim($path, '/')在循环外计算。- 进行
if ($t<>"." && $t<>"..")外部测试 - 它不需要统计路径 rtrim($path, '/') . '/' . $t每个循环计算一次 - 在 2) 内并考虑 1)。- 计算
explode(' ','B KB MB GB TB PB');一次而不是每次调用?

