Recursive function to get filesize in PHP - php

I am working on a PHP function that will scan a given folder and return the total size of all the files in the folder. My issue is that, even though it works for files stored in the root of that folder, it doesn't work for files in any subfolder. My code is:
function get_total_size($system)
{
$size = 0;
$path = scandir($system);
unset($path[0], $path[1]);
foreach($path as $file)
{
if(is_dir($file))
{
get_total_size("{$system}/{$file}");
}
else
{
$size = $size + filesize("{$system}/{$file}");
}
}
$size = $size / 1024;
return number_format($size, 2, ".", ",");
}
I'm unsetting the 0th and 1st elements of the array since these are the dot and the double dot to go up a directory. Any help would be greatly appreciated

You may try this procedure. When you check this file is_dir then you have to count the file size also. And when you check is_dir you have to concat it with root directory otherwise it show an error.
function get_total_size($system)
{
$size = 0;
$path = scandir($system);
unset($path[0], $path[1]);
foreach($path as $file)
{
if(is_dir($system.'/'.$file))
{
$size+=get_total_size("{$system}/{$file}");
}
else
{
$size = $size + filesize("{$system}/{$file}");
}
}
$size = $size / 1024;
return number_format($size, 2, ".", ",");
}
I think it will work fine
Happy coding :)

You forgot to count the size of the subfolders. you have to add it to the $size variable.
function get_total_size($system)
{
$size = 0;
$path = scandir($system);
unset($path[0], $path[1]);
foreach($path as $file)
{
if(is_dir($file))
{
$size += get_total_size("{$system}/{$file}"); // <--- HERE
}
else
{
$size = $size + filesize("{$system}/{$file}");
}
}
return $size;
}
This might however give a problem because you are using the number_format function. I would not do this and add the formatting after receiving the result of the get_total_size function.

you can use recursive directory iterator for the same. Have a look on below solution:
<?php
$total_size = 0;
$di = new RecursiveDirectoryIterator('/directory/path');
foreach (new RecursiveIteratorIterator($di) as $filename => $file) {
if($file->isFile()) {
echo $filename . ' - ' . $file->getSize() . ' bytes <br/>';
$total_size += $file->getSize();
}
}
echo $total_size; //in bytes
?>

The recursiveIterator family of classes could be of use to you.
function filesize_callback( $obj, &$total ){
foreach( $obj as $file => $info ){
if( $obj->isFile() ) {
echo 'path: '.$obj->getPath().' filename: '.$obj->getFilename().' filesize: '.filesize( $info->getPathName() ).BR;
$total+=filesize( $info->getPathName() );
} else filesize_callback( $info,&$total );
}
}
$total=0;
$folder='C:\temp';
$iterator=new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $folder, RecursiveDirectoryIterator::KEY_AS_PATHNAME ), RecursiveIteratorIterator::CHILD_FIRST );
call_user_func( 'filesize_callback', $iterator, &$total );
echo BR.'Grand-Total: '.$total.BR;

Related

Function php with loop

In index.php I have arrays listing folders. Function.php has code that counts the size of the folder. The code works when I type the folder name manually. I don't know how to make the code in function.php count for all folders in index.php. In index.php I made a loop foreach ($nameFolders as $index => $value) {echo $nameFolders[$index];} but it does not work in function.php $disk_used = foldersize ($nameFolders[$index]);
index.php
$nameFolders = array("nameFolder1", "nameFolder2", "nameFolder3");
foreach ($nameFolders as $index => $value) {
echo $nameFolders[$index];
}
include 'function.php';
function.php
$units = explode(' ', 'B KB MB GB');
$disk_used = foldersize($nameFolders[$index]);
$totalSize = format_size($disk_used);
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];
}
There are several things wrong with your code, starting with the include order. If you include (and thus declare) the functions AFTER your loop, you cannot use them inside the loop; I understand that you are trying to print all the folders with their sizes.
index.php
<?php
include_once('function.php'); // this needs to happen before.
$name_folders = array('nameFolder1', 'nameFolder2', 'nameFolder3');
// no need for key => value here if you don't use that
foreach ($name_folders as $folder) {
$disk_used = folder_size($folder);
$totalSize = format_size($disk_used);
echo "$folder: $totalSize\n";
}
function.php
<?php
$units = explode(' ', 'B KB MB GB');
function folder_size($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 = folder_size($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];
}
Please note that this "include function.php" style of PHP is how we did it in 1999, and it's not really a modern practice. Same goes for the use of global there. Try sticking to ONE naming convention: you mix camelCase with snake_case.

Calculate the weight of a directory (folder) in php

I am wanting to calculate the weight of a directory in php, then display the data as per the example below.
Example:
Storage
50 GB (14.12%) of 353 GB used
I have the following function, with which I show in a list the folders that are inside the root.
<?php
$dir = ('D:\data');
echo "Size : " Fsize($dir);
function Fsize($dir)
{
if (is_dir($dir))
{
if ($gd = opendir($dir))
{
$cont = 0;
while (($file = readdir($gd)) !== false)
{
if ($file != "." && $file != ".." )
{
if (is_dir($file))
{
$cont += Fsize($dir."/".$file);
}
else
{
$cont += filesize($dir."/".$file);
echo "file : " . $dir."/".$file . " " . filesize($dir."/".$file)."<br />";
}
}
}
closedir($gd);
}
}
return $cont;
}
?>
The size it shows me of the folder is 3891923, but it is not the real size, when validating the directory the real size is 191791104 bytes
Can you help me, please?
Your test for directory is incorrect here:
if (is_dir($file)) // This test is missing the directory component
{
$cont += Fsize($dir."/".$file);
}
else
Try:
if (is_dir("$dir/$file")) // This test adds the directory path
{
$cont += Fsize($dir."/".$file);
}
else
PHP offers a number of iterators that can simplify operations like this:
$path = "path/to/folder";
$Directory = new RecursiveDirectoryIterator($path);
$Iterator = new RecursiveIteratorIterator($Directory);
$Iterator->setFlags(FilesystemIterator::SKIP_DOTS);
$totalFilesize = 0;
foreach($Iterator as $file){
if ($file->isFile()) {
$totalFilesize += $file->getSize();
}
}
echo "Total: $totalFilesize";

Getting RecursiveIteratorIterator to skip a specified directory

I'm using this function to get the file size & file count from a given directory:
function getDirSize($path) {
$total_size = 0;
$total_files = 0;
$path = realpath($path);
if($path !== false){
foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS)) as $object) {
$total_size += $object->getSize();
$total_files++;
}
}
$t['size'] = $total_size;
$t['count'] = $total_files;
return $t;
}
I need to skip a single directory (in the root of $path). Is there a simple way to do this? I looked at other answers referring to FilterIterator, but I'm not very familiar with it.
If you don't want to involve a FilterIterator you can add a simple path match:
function getDirSize($path, $ignorePath) {
$total_size = 0;
$total_files = 0;
$path = realpath($path);
$ignorePath = realpath($path . DIRECTORY_SEPARATOR . $ignorePath);
if($path !== false){
foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS)) as $object) {
if (strpos($object->getPath(), $ignorePath) !== 0) {
$total_size += $object->getSize();
$total_files++;
}
}
}
$t['size'] = $total_size;
$t['count'] = $total_files;
return $t;
}
// Get total file size and count of current directory,
// excluding the 'ignoreme' subdir
print_r(getDirSize(__DIR__ , 'ignoreme'));

i want get the sum of files size in folder by php

I have a folder named files, how do I determine the sum of size of it's files?
With DirectoryIterator and SplFileInfo
$totalSize = 0;
foreach (new DirectoryIterator('/path/to/dir') as $file) {
if ($file->isFile()) {
$totalSize += $file->getSize();
}
}
echo $totalSize;
and in case you need that including subfolders:
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator('/path/to/dir')
);
$totalSize = 0;
foreach ($iterator as $file) {
$totalSize += $file->getSize();
}
echo $totalSize;
And you can run $totalSize through the code we gave you to format 6000 to 6k for a more human readable output. You'd have to change all 1000s to 1024 though.
echo array_sum(array_map('filesize', glob('*')));
Well try this using filesize() to calculate file size while iterating through all the files and sub-directory files.
<?php
function get_dir_size($dir_name){
$dir_size =0;
if (is_dir($dir_name)) {
if ($dh = opendir($dir_name)) {
while (($file = readdir($dh)) !== false) {
if($file !=”.” && $file != “..”){
if(is_file($dir_name.”/”.$file)){
$dir_size += filesize($dir_name.”/”.$file);
}
/* check for any new directory inside this directory */
if(is_dir($dir_name.”/”.$file)){
$dir_size += get_dir_size($dir_name.”/”.$file);
}
}
}
}
}
closedir($dh);
return $dir_size;
}
$dir_name = “directory name here”;
/* 1048576 bytes == 1MB */
$total_size= round((get_dir_size($dir_name) / 1048576),2) ;
print “Directory $dir_name size : $total_size MB”;
?>
if you have access to exec function you can use this code:
exec("du {directory_path_you_want_see_size} -s 2>&1",$output);
echo intval($output[0]) ;
example:
exec("du /home/ -s 2>&1",$output);
echo intval($output[0]) ;

Recursively counting files with PHP

Simple question for a newb and my Google-Fu is failing me. Using PHP, how can you count the number of files in a given directory, including any sub-directories (and any sub-directories they might have, etc.)? e.g. if directory structure looks like this:
/Dir_A/
/Dir_A/File1.blah
/Dir_A/Dir_B/
/Dir_A/Dir_B/File2.blah
/Dir_A/Dir_B/File3.blah
/Dir_A/Dir_B/Dir_C/
/Dir_A/Dir_B/Dir_C/File4.blah
/Dir_A/Dir_D/
/Dir_A/Dir_D/File5.blah
The script should return with '5' for "./Dir_A".
I've cobbled together the following but it's not quite returning the correct answer, and I'm not sure why:
function getFilecount( $path = '.', $filecount = 0, $total = 0 ){
$ignore = array( 'cgi-bin', '.', '..', '.DS_Store' );
$dh = #opendir( $path );
while( false !== ( $file = readdir( $dh ) ) ){
if( !in_array( $file, $ignore ) ){
if( is_dir( "$path/$file" ) ){
$filecount = count(glob( "$path/$file/" . "*"));
$total += $filecount;
echo $filecount; /* debugging */
echo " $total"; /* debugging */
echo " $path/$file"; /* debugging */
getFilecount( "$path/$file", $filecount, $total);
}
}
}
return $total;
}
I'd greatly appreciate any help.
This should do the trick:
function getFileCount($path) {
$size = 0;
$ignore = array('.','..','cgi-bin','.DS_Store');
$files = scandir($path);
foreach($files as $t) {
if(in_array($t, $ignore)) continue;
if (is_dir(rtrim($path, '/') . '/' . $t)) {
$size += getFileCount(rtrim($path, '/') . '/' . $t);
} else {
$size++;
}
}
return $size;
}
Use the SPL, then see if you still get an error.
RecursiveDirectoryIterator
Usage example:
<?php
$path = realpath('/etc');
$objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::SELF_FIRST);
foreach($objects as $name => $object){
echo "$name\n";
}
?>
This prints a list of all files and directories under $path (including $path ifself). If you want to omit directories, remove the RecursiveIteratorIterator::SELF_FIRST part.
Then just use isDir()
based on Andrew's answer...
$path = realpath('my-big/directory');
$objects = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($path),
RecursiveIteratorIterator::SELF_FIRST
);
$count=iterator_count($objects);
echo number_format($count); //680,642 wooohaah!
like that i'm able to count (not listing) thousands & thousands files. 680,642 files in less than 4.6 seconds actually ;)
Paolo Bergantino was almost with his code, but the function will still count .DS_Store files since he misspelled it. Correct Code below
function getFileCount($path) {
$size = 0;
$ignore = array('.','..','cgi-bin','.DS_Store');
$files = scandir($path);
foreach($files as $t) {
if(in_array($t, $ignore)) continue;
if (is_dir(rtrim($path, '/') . '/' . $t)) {
$size += getFileCount(rtrim($path, '/') . '/' . $t);
} else {
$size++;
}
}
return $size;
}
Why are you passing $filecount? The [passed-in] value is not being used; the only usage is at "$total += $filecount" and you're overriding $filecount just before that.
You're missing the case when the function encounters a regular (non-dir) file.
Edit: I just noticed the call to glob(). It's not necessary. Your function is recursively touching every file in the whole directory tree, anyway. See #Paolo Bergantino's answer.
Check the PHP manual on glob() function: http://php.net/glob
It has examples in comments as to how to make it recursive.

Categories