34

I'm trying to return the files in a specified directory using a recursive search. I successfully achieved this, however I want to add a few lines of code that will allow me to specify certain extensions that I want to be returned.

For example return only .jpg files in the directory.

Here's my code,

<?php
$it = new RecursiveDirectoryIterator("L:\folder\folder\folder");
foreach(new RecursiveIteratorIterator($it) as $file) {
echo $file . "<br/> \n";
}
?>

please let me know what I can add to the above code to achieve this, thanks

9 Answers 9

47
<?php
$it = new RecursiveDirectoryIterator("L:\folder\folder\folder");
$display = Array ( 'jpeg', 'jpg' );
foreach(new RecursiveIteratorIterator($it) as $file)
{
    if (in_array(strtolower(array_pop(explode('.', $file))), $display))
        echo $file . "<br/> \n";
}
?>
1
  • 4
    Only variables should be passed by reference
    – Sky
    Commented Jul 13, 2020 at 7:48
20

You should create a filter:

class JpegOnlyFilter extends RecursiveFilterIterator
{
    public function __construct($iterator)
    {
        parent::__construct($iterator);
    }

    public function accept()
    {
        return $this->current()->isFile() && preg_match("/\.jpe?g$/ui", $this->getFilename());
    }

    public function __toString()
    {
        return $this->current()->getFilename();
    }
}

$it = new RecursiveDirectoryIterator("L:\folder\folder\folder");
$it = new JpegOnlyFilter($it);
$it = new RecursiveIteratorIterator($it);

foreach ($it as $file)
    ...
1
  • 2
    This will not work, if you stop when found a directory (if ->isFile()) the iterator don't deep in that directory to scan more files and directories, is more complex than one-line if.
    – Tecnocat
    Commented Sep 6, 2017 at 13:11
8

Try this, it uses an array of allowed file types and only echos out the file if the file extension exists within the array.

<?php
$it = new RecursiveDirectoryIterator("L:\folder\folder\folder");
$allowed=array("pdf","txt");
foreach(new RecursiveIteratorIterator($it) as $file) {
    if(in_array(substr($file, strrpos($file, '.') + 1),$allowed)) {
        echo $file . "<br/> \n";
    }
}
?>

You may also find that you could pass an array of allowed file types to your RecursiveDirectoryIterator class and only return files that match.

0
6

Let PHP do the job:

$directory = new RecursiveDirectoryIterator('path/to/directory/');
$iterator  = new RecursiveIteratorIterator($directory);
$regex     = new RegexIterator($iterator, '/\.jpe?g$/i', RecursiveRegexIterator::GET_MATCH);

echo '<pre>';
print_r($regex);
1
  • print_r($regex); just give me... RegexIterator Object ( [replacement] => ) php.net/manual/en/regexiterator.construct.php It is needed to loop with something such as foreach. foreach ($regexIterator as $value) { echo $value . "\n"; }
    – vee
    Commented Feb 4, 2020 at 13:39
1

Regarding the top voted answer: I created this code which is using fewer functions, only 3, isset(), array_flip(), explode() instead of 4 functions. I tested the top voted answer and it was slower than mine. I suggest giving mine a try:

$it = new RecursiveDirectoryIterator("L:\folder\folder\folder");
foreach(new RecursiveIteratorIterator($it) as $file) {
    $FILE = array_flip(explode('.', $file));
    if (isset($FILE['php']) || isset($FILE['jpg'])) {
        echo  $file. "<br />";
    }
}
1
  • This breaks on a case like php.png. It is not a php or jpg file; it is an png file named php. It is important to precisely extract the file extension when validating. Speed of execution is moot if it doesn't deliver the desired effect. Commented Feb 13, 2019 at 6:35
1

None of these worked for my case. So i wrote this function, not sure about efficiency, I just wanted to remove some duplicate photos quickly. Hope it helps someone else.

function rglob($dir, $pattern, $matches=array())
{
    $dir_list = glob($dir . '*/');
    $pattern_match = glob($dir . $pattern);

    $matches = array_merge($matches, $pattern_match);

    foreach($dir_list as $directory)
    {
        $matches = rglob($directory, $pattern, $matches);
    }

    return $matches;
}

$matches = rglob("C:/Bridge/", '*(2).ARW');

Only slight improvement that could be made is that currently for it to work you have to have a trailing forward slash on the start directory.

1

In this sample code;

  • You can set any path for $directory variable, for example ./, 'L:\folder\folder\folder' or anythings...
  • And also you can set a pattern file name in $pattern optional, You can put '/\.jpg$/' for every file with .jpg extension, and also if you want to find all files, can just use '//' for this variable.
$directory = 'L:\folder\folder\folder';
$pattern = '/\.jpg$/'; //use "//" for all files
$directoryIterator = new RecursiveDirectoryIterator($directory);
$iteratorIterator = new RecursiveIteratorIterator($directoryIterator);
$regexIterator = new RegexIterator($iteratorIterator, $pattern);
foreach ($regexIterator as $file) {
    if (is_dir($file)) continue;
    echo "$file\n";
}
0

here is the correct way to search in folders and sub folders

$it = new RecursiveDirectoryIterator(__DIR__);
$findExts = Array ( 'jpeg', 'jpg' );
foreach(new RecursiveIteratorIterator($it) as $file)
{        
    $ext = pathinfo($file, PATHINFO_EXTENSION);
    if(in_array($ext, $findExts)){
        echo $file.PHP_EOL;
    }
}
-1

You might want to check out this page about using glob() for a similar search:

http://www.electrictoolbox.com/php-glob-find-files/

2
  • Your source is good, but try give a constructive answer with example, how to resource can be used for the particular case and only add the link as reference.
    – d.raev
    Commented Nov 25, 2014 at 12:35
  • I don't think glob handles recursion, either, which was a part of the question.
    – Oded
    Commented Aug 13, 2015 at 21:14

Not the answer you're looking for? Browse other questions tagged or ask your own question.