I need to get a total count of JPG files within a specified directory, including ALL it\'s subdirectories. No sub-sub directories.
Structure looks like this :
<You could do it like this using the RecursiveDirectoryIterator
<?php
function scan_dir($path){
$ite=new RecursiveDirectoryIterator($path);
$bytestotal=0;
$nbfiles=0;
foreach (new RecursiveIteratorIterator($ite) as $filename=>$cur) {
$filesize=$cur->getSize();
$bytestotal+=$filesize;
$nbfiles++;
$files[] = $filename;
}
$bytestotal=number_format($bytestotal);
return array('total_files'=>$nbfiles,'total_size'=>$bytestotal,'files'=>$files);
}
$files = scan_dir('./');
echo "Total: {$files['total_files']} files, {$files['total_size']} bytes\n";
//Total: 1195 files, 357,374,878 bytes
?>
The answer by Developer is actually brilliant! Use it like this to make it work:
System("find . -type f -print | wc -l");
A for each loops could do the trick more quickly ;-)
As I remember, opendir is derivated from the SplFileObject class which is a RecursiveIterator , Traversable , Iterator , SeekableIterator class, so, you don't need a while loops if you use the SPL standard PHP Library to retrive the whole images count even on subdirectory.
But, it's been a while that I didn't used PHP so I might made a mistake.
error_reporting(E_ALL);
function printTabs($level)
{
echo "<br/><br/>";
$l = 0;
for (; $l < $level; $l++)
echo ".";
}
function printFileCount($dirName, $init)
{
$fileCount = 0;
$st = strrpos($dirName, "/");
printTabs($init);
echo substr($dirName, $st);
$dHandle = opendir($dirName);
while (false !== ($subEntity = readdir($dHandle)))
{
if ($subEntity == "." || $subEntity == "..")
continue;
if (is_file($dirName . '/' . $subEntity))
{
$fileCount++;
}
else //if(is_dir($dirName.'/'.$subEntity))
{
printFileCount($dirName . '/' . $subEntity, $init + 1);
}
}
printTabs($init);
echo($fileCount . " files");
return;
}
printFileCount("/var/www", 0);
Just checked, it's working. But the alignment of results is bad,logic works
if anyone is looking to count total number of files and directories.
Show/count total dir and sub dir count
find . -type d -print | wc -l
Show/count total number of files in main and sub dir
find . -type f -print | wc -l
Show/count only files from current dir (no sub dir)
find . -maxdepth 1 -type f -print | wc -l
Show/count total directories and files in current dir (no sub dir)
ls -1 | wc -l
For the fun of it I've whipped this together:
class FileFinder
{
private $onFound;
private function __construct($path, $onFound, $maxDepth)
{
// onFound gets called at every file found
$this->onFound = $onFound;
// start iterating immediately
$this->iterate($path, $maxDepth);
}
private function iterate($path, $maxDepth)
{
$d = opendir($path);
while ($e = readdir($d)) {
// skip the special folders
if ($e == '.' || $e == '..') { continue; }
$absPath = "$path/$e";
if (is_dir($absPath)) {
// check $maxDepth first before entering next recursion
if ($maxDepth != 0) {
// reduce maximum depth for next iteration
$this->iterate($absPath, $maxDepth - 1);
}
} else {
// regular file found, call the found handler
call_user_func_array($this->onFound, array($absPath));
}
}
closedir($d);
}
// helper function to instantiate one finder object
// return value is not very important though, because all methods are private
public static function find($path, $onFound, $maxDepth = 0)
{
return new self($path, $onFound, $maxDepth);
}
}
// start finding files (maximum depth is one folder down)
$count = $bytes = 0;
FileFinder::find('.', function($file) use (&$count, &$bytes) {
// the closure updates count and bytes so far
++$count;
$bytes += filesize($file);
}, 1);
echo "Nr files: $count; bytes used: $bytes\n";
You pass the base path, found handler and maximum directory depth (-1 to disable). The found handler is a function you define outside, it gets passed the path name relative from the path given in the find()
function.
Hope it makes sense and helps you :)