33

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

Jan Hančič
  • 53,269
  • 16
  • 95
  • 99
Jason
  • 363
  • 1
  • 3
  • 5

9 Answers9

46
<?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";
}
?>
Jan Hančič
  • 53,269
  • 16
  • 95
  • 99
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)
    ...
Greg
  • 316,276
  • 54
  • 369
  • 333
  • 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 Sep 06 '17 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.

Ben Everard
  • 13,652
  • 14
  • 67
  • 96
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);
Mike Doe
  • 16,349
  • 11
  • 65
  • 88
  • `print_r($regex);` just give me... ```RegexIterator Object ( [replacement] => )``` https://www.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 Feb 04 '20 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 />";
    }
}
Nisse Engström
  • 4,738
  • 23
  • 27
  • 42
Ahmad ghoneim
  • 844
  • 7
  • 13
  • 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. – mickmackusa Feb 13 '19 at 06: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";
}
Nabi K.A.Z.
  • 9,887
  • 6
  • 59
  • 81
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;
    }
}
aldo
  • 312
  • 3
  • 12
-1

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

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

user1158023
  • 337
  • 2
  • 6
  • 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 Nov 25 '14 at 12:35
  • I don't think glob handles recursion, either, which was a part of the question. – Oded Aug 13 '15 at 21:14