php recursive folder readdir vs find performance
Asked Answered
O

2

28

i came across few articles about performance and readdir here is the php script:

function getDirectory( $path = '.', $level = 0 ) { 
    $ignore = array( 'cgi-bin', '.', '..' );
    $dh = @opendir( $path );
    while( false !== ( $file = readdir( $dh ) ) ){
        if( !in_array( $file, $ignore ) ){
            $spaces = str_repeat( ' ', ( $level * 4 ) );
            if( is_dir( "$path/$file" ) ){
                echo "$spaces $file\n";
                getDirectory( "$path/$file", ($level+1) );
            } else {
                echo "$spaces $file\n";
            }
        }
    }
    closedir( $dh );
}
getDirectory( "." );  

this echo the files/ folders correctly.

now i found this:

$t = system('find');
print_r($t);

which also find all the folders and files then i can create an array like the first code.

i think the system('find'); is faster than the readdir but i want to know if it'S a good practice? thank you very much

Outofdoors answered 30/11, 2011 at 1:35 Comment(4)
A system call certainly isn't portable. Your example code is dependent upon a *nix OS.Enyedy
i have centos 5 with apache and php+mysql that is ok?Outofdoors
It's also a bad idea to get used to using system() calls. They should be fine without parameters, but if you construct them dynamically based on user input, you're likely to create bad security holes.Futch
@Inerdial oh i didn't think about that thanksOutofdoors
K
36

Here's my benchmark using a simple for loop with 10 iteration on my server:

$path = '/home/clad/benchmark/';
// this folder has 10 main directories and each folder as 220 files in each from 1kn to 1mb

// glob no_sort = 0.004 seconds but NO recursion
$files = glob($path . '/*', GLOB_NOSORT);

// 1.8 seconds - not recommended
exec('find ' . $path, $t);
unset($t);

// 0.003 seconds
if ($handle = opendir('.')) {
 while (false !== ($file = readdir($handle))) {
  if ($file != "." && $file != "..") {
   // action
  }
 }
 closedir($handle);
}

// 1.1 seconds to execute
$path = realpath($path);
$objects = new RecursiveIteratorIterator(
 new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::SELF_FIRST);
  foreach($objects as $name => $object) {
   // action
  }
}

Clearly the readdir is faster to use specially if you have lots of traffic on your site.

Kaleb answered 30/11, 2011 at 13:55 Comment(2)
Good answer, but am I missing something... the readdir() solution on its own is not recursive. Will this not skew the results?Bligh
How to benchmark individual functions like you, aki?Complicacy
C
2

'find' is not portable, it's a unix/linux command. readdir() is portable and will work on Windows or any other OS. Moreover, 'find' without any parameters is recursive, so if you're in a dir with lots of subdirs and files, you will get to see all of them, rather than only the contents of that $path.

Cleromancy answered 30/11, 2011 at 1:40 Comment(5)
Although I see that your function is recursive as well, so ignore the rant about recursiveness. Note though, that output of 'find' is also formatted in a peculiar way.Cleromancy
i never used windows so it's unix or linux only, for the formating i can deal withOutofdoors
Well, let's put it this way. Speed-wise it won't matter much, but to control behavior of function using find - you'll need to tweak 'find' commandline parameters, rather than using code-way of controlling your function behavior. I, for one, wouldn't go with find, unless there would be a very specific reason to do it.Cleromancy
you saying if i look for files only i can use: -type f instead of in the php is_file or is_dir?Outofdoors
Yep, you can do that if you want to look for files only.Cleromancy

© 2022 - 2024 — McMap. All rights reserved.