Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to recursively iterate through files in PHP?

Tags:

loops

php

I have set up a basic script that is posting an array of paths to find template files inside them; currently it's only searching two levels deep and I'm having some troubles getting my head around the logic for an extensive loop to iterate all child directories until the length is 0.

So if I have a structure like this:

./components
./components/template.html
./components/template2.html
./components/side/template.html
./components/side/template2.html
./components/side/second/template.html
./components/side/second/template2.html
./components/side/second/third/template.html
./components/side/second/third/template2.html

It's only searching up to the "side" directory for .html files when ideally I want it to check all child directories and the passed directory for .html files. Here is my working code so far:

<?php
function getFiles($path){
    $dh  = opendir($path);
    foreach(glob($path.'/*.html') as $filename){
        $files[] = $filename;
    }
    if (isset($files)) {
        return $files;
    }
}
foreach ($_POST as $path) {
    foreach (glob($path . '/*' , GLOB_ONLYDIR) as $secondLevel) {
        $files[] = getFiles($secondLevel);
    }
    $files[] = getFiles($path);
}
sort($files);
print_r(json_encode($files));
?>
like image 703
Simon Staton Avatar asked Sep 18 '14 10:09

Simon Staton


2 Answers

PHP has the perfect solution for you built in.

Example

// Construct the iterator
$it = new RecursiveDirectoryIterator("/components");

// Loop through files
foreach(new RecursiveIteratorIterator($it) as $file) {
    if ($file->getExtension() == 'html') {
        echo $file;
    }
}

Resources

  • DirectoryIterator - Manual
like image 98
Peter Avatar answered Nov 12 '22 11:11

Peter


PHP 5 introduces iterators to iterate quickly through many elements.

You can use RecursiveDirectoryIterator to iterate recursively through directories.

You can use RecursiveIteratorIterator on the result to have a flatten view of the result.

You can use RegexIterator on the result to filter based on a regular expression.

 $directory_iterator = new RecursiveDirectoryIterator('.');
 $iterator       = new RecursiveIteratorIterator($directory_iterator);
 $regex_iterator = new RegexIterator($iterator, '/\.php$/');
 $regex_iterator->setFlags(RegexIterator::USE_KEY);
 foreach ($regex_iterator as $file) {
    echo $file->getPathname() . PHP_EOL;
 }

With iterators, there are lot of ways to do the same thing, you can also use a FilterIterator (see the example on the page)

For instance, if you want to select the files modified this week, you can use the following:

  $directory_iterator = new RecursiveDirectoryIterator('.');
  $iterator       = new RecursiveIteratorIterator($directory_iterator);

  class CustomFilterIterator extends FilterIterator {
       function accept() {
            $current=$this->getInnerIterator()->current();
            return ($current->isFile()&&$current->getMTime()>time()-3600*24*7);
       }
  }

  $filter_iterator=new CustomFilterIterator($iterator);
  foreach ($filter_iterator as $file) {
     echo $file->getPathname() . PHP_EOL;
  }
like image 10
Adam Avatar answered Nov 12 '22 13:11

Adam