I would like to count all characters in text files in certain path, so i've wrote the following code
<?PHP
$files = glob('my/files/path/*.txt', GLOB_BRACE);
foreach($files as $file) {
$str = file_get_contents($file) or dir("can not read file");
$numCharSpace = strlen($str);
echo "Counted " .$numCharSpace. " character(s).<br>";
}
?>
Let say, we have 4 files inside this path so it will print out the following
Counted 201 character(s).
Counted 99 character(s).
Counted 88 character(s).
Counted 112 character(s).
How can i get the total of all which should be 500 character(s) so how to print out the count of all results which are inside foreach(); loop.
With strlen you get the number of the bytes of the file. So, you can as well get that directly, without the need to read the file contents.
$numberOfChars = array_sum(
array_map('filesize', glob('my/files/path/*.txt', GLOB_BRACE))
);
What this does is get the file size for each one of the files returned by glob, and sum them using array_sum.
You can use a variable to sum. Then you could use filesize() to get total bytes of the file instead of load it:
$files = glob('my/files/path/*.txt', GLOB_BRACE);
$total = 0;
foreach($files as $file) {
$numCharSpace = filesize($file);
$total += $numCharSpace ;
}
echo "Counted " .$total. " character(s).<br>";
<?PHP
$files = glob('my/files/path/*.txt', GLOB_BRACE);
$Total = 0;
foreach($files as $file) {
$str = file_get_contents($file) or dir("can not read file");
$numCharSpace = strlen($str);
echo "Counted " .$numCharSpace. " character(s).<br>";
$Total += $numCharSpace;
}
echo "Total " .$Total. " characters.<br>";
?>
Following code should work :
$files = glob('my/files/path/*.txt', GLOB_BRACE);
$numCharSpace = 0;
foreach($files as $file) {
$str = file_get_contents($file) or dir("can not read file");
$numCharSpace = $numCharSpace + strlen($str);
}
echo "Counted " .$numCharSpace. " character(s).";
If there are 2 folder name 1 and 3 in ./path/1 ./path/3, now I try to add a new folder, but how to sort the folder name already exist and find the missing number is 2?
<?php
$file = 0;
$folder = 0;
$dir = new RecursiveDirectoryIterator('./img/product/tmp', FilesystemIterator::SKIP_DOTS);
$it = new RecursiveIteratorIterator($dir, RecursiveIteratorIterator::SELF_FIRST);
$it->setMaxDepth(0);
foreach ($it as $fileinfo) {
if ($fileinfo->isDir()) {
printf("Folder - %s\n", $fileinfo->getFilename());
$folder++;
} elseif ($fileinfo->isFile()) {
printf("File From %s - %s\n", $it->getSubPath(), $fileinfo->getFilename());
$file++;
}
}
if(/* find the missing number */){
$folder_new = //missing number
$dir = './path/'.$folder_new;
if(!is_dir($dir)){
mkdir($dir);
}else{
$folder_new = $folder+1;
$dir = './path/'.$folder_new;
if(!is_dir($dir)){
mkdir($dir);
}
}
?>
basicly:
$root = $_SERVER['DOCUMENT_ROOT']; // '.' doesn't work on the backend for going to the root.
$path = "$root/path/";
$dirs = glob("$path*"); // this creates an array with everything inside $path
sort($dirs); //you wanted the directories sorted
//deleting the files (not dirs)
foreach($dirs as $k => $dir){
if(!is_dir($dir)){
unset($dirs[$k]);
}
}
$max = array_max($dirs); //folder number with the highest number as name.
// this is the part finding out what number is missing
for($i = 0; $i <= $max; $i++){
if(!is_dir($path.$i){
mkdir($path.$i);
}
}
didn't tested, just wrote it out of my head, hope it works for you :)
I would have though that if you can get a list of folders in the directory (./path),
Then you can compare to see which directories exist:
for ( $i = 0; $i < 100; $i++ ) {
if ( ! is_dir( './path/' . $i ) ) {
mkdir( './path/' . $i );
}
}
are you trying to do something like this ??
<?php
$to = 5;
for ($i = 1; $i <= $to; $i++) {
echo '<br/>';
$my_path = dirname(__FILE__) . '/path/' . $i;
if (!is_dir($my_path)) {
echo $i . ' dir not exist ';
if (mkdir($my_path, 0777)) {
echo $i . ' dir created ';
} else {
echo $i . ' dir not created ';
}
} else {
echo $i . ' dir already exists ';
}
}
?>
How to make a little function that given a directory it returns the number of lines (counts \r\n) of .php files between <?php and ?>?
Usage:
echo countsLineOfCode('D:/dir/code/');
// returns 323;
function countLinesOfCode($path) {
$lines = 0;
$items = glob(rtrim($path, '/') . '/*');
foreach($items as $item) {
if (is_file($item) AND pathinfo($item, PATHINFO_EXTENSION) == 'php') {
$fileContents = file_get_contents($item);
preg_match_all('/<\?(?:php)?(.*?)($|\?>)/s', $fileContents, $matches);
foreach($matches[1] as $match) {
$lines += substr_count($match, PHP_EOL);
}
} else if (is_dir($item)) {
$lines += countLinesOfCode($item);
continue;
}
}
return $lines;
}
var_dump(countLinesOfCode(dirname(__FILE__))); // int(31) (works for me)
Keep in mine this is counting newlines, not end of line character ;. For example, the line below will be considered one line...
var_dump($files); echo 'something'; exit;
It also counts lines without any PHP code, e.g. the below code will be 4 lines...
<?php
$a = 3;
It also doesn't count the <?php or closing (if present).
Let me know if it (a) shouldn't match empty lines, (b) should match semi colons instead (will need to ensure they are not appearing within a string) and/or (c) it should match the opening and closing tag (will be easy as changing $matches[1] in the foreach to $matches[0]).
PHPLOC
A tool for quickly measuring the size and analyzing the structure of a PHP project.
recursive version of alex function
function countLinesOfCode($path) {
$lines = 0;
$files = glob(rtrim($path, '/') . '/*');
foreach($files as $file) {
if (is_dir($file)){
if ($file=='.' || $file=='..')
continue;
$lines+=countLinesOfCode($file);
} else if (substr($file,-4)!='.php')
continue;
echo 'Counting on ' . $file .'<br>';
$fileContents = file_get_contents($file);
preg_match_all('/<\?(?:php)?(.*?)(?:$|\?>)/s', $fileContents, $matches);
foreach($matches[1] as $match) {
$lines += substr_count($match, PHP_EOL);
}
}
return $lines;
}
I made it work based on this Answer and the documentation for RecursiveDirectoryIterator.
$path = realpath( '/path/to/directory' );
$lines = $files = 0;
$objects = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator( $path ),
RecursiveIteratorIterator::SELF_FIRST
);
foreach( $objects as $name => $fileinfo )
{
if ( !$fileinfo->isFile() )
continue;
if( false === strpos( $name,'.php' ) )
continue;
$files++;
$read = $fileinfo->openFile();
$read->setFlags( SplFileObject::READ_AHEAD );
$lines += iterator_count( $read ) - 1; // -1 gives the same number as "wc -l"
}
printf( "Found %d lines in %d files.", $lines, $files );
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
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?
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:
Converts $path to realpath
Performs iteration only if path is valid and folder exists
Skips . and .. files
Optimized for performance
The following are other solutions offered elsewhere:
If on a 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';
}
?>
Else, if on a 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;
?>
directory size using php filesize and RecursiveIteratorIterator.
This works with any platform which is having php 5 or higher version.
/**
* Get the directory size
* #param string $directory
* #return integer
*/
function dirSize($directory) {
$size = 0;
foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory)) as $file){
$size+=$file->getSize();
}
return $size;
}
A pure php example.
<?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];
}
?>
function get_dir_size($directory){
$size = 0;
$files = glob($directory.'/*');
foreach($files as $path){
is_file($path) && $size += filesize($path);
is_dir($path) && $size += get_dir_size($path);
}
return $size;
}
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.
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);
}
}
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).
If you look at Jonathan's answer he uses the du command. 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!
What to look out for
When running du on a newly created directory, it may return 4K instead of 0. This may even get more confusing after having deleted files from the directory in question, having du reporting a total directory size that does not correspond to the sum of the sizes of the files within it. Why? The command du returns a report based on some file settings, as Hermann Ingjaldsson commented on this post.
The solution
To form a solution that behaves like some of the PHP-only scripts posted here, you can use ls command and pipe it to awk like this:
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:
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;
}
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.
$file_directory = './directory/path';
$output = exec('du -sk ' . $file_directory);
$filesize = trim(str_replace($file_directory, '', $output)) * 1024;
Returns the $filesize in bytes.
Johnathan Sampson's Linux example didn't work so good for me. Here's an improved version:
function getDirSize($path)
{
$io = popen('/usr/bin/du -sb '.$path, 'r');
$size = intval(fgets($io,80));
pclose($io);
return $size;
}
It works perfectly fine .
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;
}
There are several things you could do to optimise the script - but maximum success would make it IO-bound rather than CPU-bound:
Calculate rtrim($path, '/') outside the loop.
make if ($t<>"." && $t<>"..") the outer test - it doesn't need to stat the path
Calculate rtrim($path, '/') . '/' . $t once per loop - inside 2) and taking 1) into account.
Calculate explode(' ','B KB MB GB TB PB'); once rather than each call?
PHP get directory size (with FTP access)
After hard work, this code works great!!!! and I want to share with the community (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);
Good code!
Fernando
Object Oriented Approach :
/**
* 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;
}
Fast and Furious Approach :
function dir_size2($dir)
{
$line = exec('du -sh ' . $dir);
$line = trim(str_replace($dir, '', $line));
return $line;
}
Code adjusted to access main directory and all sub folders within it. This would return the full directory size.
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;
}
if you are hosted on Linux:
passthru('du -h -s ' . $DIRECTORY_PATH)
It's better than foreach
Regarding Johnathan Sampson's Linux example, watch out when you are doing an intval on the outcome of the "du" function, if the size is >2GB, it will keep showing 2GB.
Replace:
$totalSize = intval(fgets($io, 80));
by:
strtok(fgets($io, 80), " ");
supposed your "du" function returns the size separated with space followed by the directory/file name.
Just another function using native php functions.
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;
}
NOTE: this function returns the files sizes, NOT the size on disk
Evolved from Nate Haugs answer I created a short function for my project:
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);
}
A one-liner solution. Result in bytes.
$size=array_sum(array_map('filesize', glob("{$dir}/*.*")));
Added bonus: you can simply change the file mask to whatever you like, and count only certain files (eg by extension).
This is the simplest possible algorithm to find out directory size irrespective of the programming language you are using.
For PHP specific implementation. go to: Calculate Directory Size in PHP | Explained with Algorithm | Working Code
i need help with disk_total_space function..
i have this on my code
<?php
$sql="select * from users order by id";
$result=mysql_query($sql);
while($row=mysql_fetch_array($result)) {
?>
Name : <?php echo $row['name']; ?>
Email : <?php echo $row['email']; ?>
Diskspace Available : <?php
$dir = "C:/xampp/htdocs/freehosting/".$row['name'];
disk_total_space($dir);
} ?>
However this return me same disk space for every users ..
Anyone can shed me some light?
thanks :)
http://us2.php.net/disk_total_space says,
"Given a string containing a directory, this function will return the total number of bytes on the corresponding filesystem or disk partition."
You're likely seeing the total_space of C:
Alternative solutions do exist for both Windows and Linux.
I think what you want is something like this:
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>';
}
edit: the recursive function had a bug in it originally. Now it should also read folders inside the original folders, and folders inside those folders, and so on.
The comments on the function on PHP.net appear to indicate that this gives the space of the drive/partition $dir is in, not the size of $dir itself.
I think that method will only tell you information about the filesystem or partition the given directory is on. You could try simply shelling out to du though:
$space_used=`du -sh $dir`;
-s summarizes the entire dir, -h returns the result in "human" units like MB and GB.
Edit: apologies, I missed that this was on WIndows. WIll leave the answer in case it helps someone searching for a similar problem. For windows, try this suggestion in the PHP manual
According to the docs for disk_total_space(), the value returned is for the filesystem the directory is located on. It doesn't count the space used in a directory + its subdirectories.
You could shell out to du or for a more portable solution:
$total = 0;
foreach (new RecursiveDirectoryIterator($dir) as $entry)
{
if ($entry->isFile())
$total += $entry->getSize();
}
You could use the function:
function size_directory($ruta)
{
$gestor = opendir($ruta);
$total = 0;
while (($archivo = readdir($gestor)) !== false) {
$ruta_completa = $ruta . "/" . $archivo;
if ($archivo != "." && $archivo != "..") {
$total += filesize($ruta_completa);
}
}
return round($total / 1024, 0);
}