169

I'm looking for a PHP script that loops through all of the files in a directory so I can do things with the filename, such as format, print or add it to a link. I'd like to be able to sort the files by name, type or by date created/added/modified. (Think fancy directory "index".) I'd also like to be able to add exclusions to the list of files, such as the script itself or other "system" files. (Like the . and .. "directories".)

Being that I'd like to be able to modify the script, I'm more interested in looking at the PHP docs and learning how to write one myself. That said, if there are any existing scripts, tutorials and whatnot, please let me know.

Moshe
  • 57,511
  • 78
  • 272
  • 425
  • http://stackoverflow.com/questions/1086105/get-the-files-inside-a-directory/1086110#1086110 – zloctb Oct 28 '15 at 12:05

9 Answers9

292

You can use the DirectoryIterator. Example from php Manual:

<?php
$dir = new DirectoryIterator(dirname(__FILE__));
foreach ($dir as $fileinfo) {
    if (!$fileinfo->isDot()) {
        var_dump($fileinfo->getFilename());
    }
}
?>
  • 3
    Note: many servers don't have SPL installed, so you won't be able to use the DirectoryIterator class (see my alternative post below). Use this if you can though! – NexusRex Apr 11 '11 at 23:23
  • 7
    Note[2]: Make sure you understand that the ``dirname()`` function above will get the parent folder of whatever path you put there. In my case, I assumed dirname was a wrapper for the directory name/path, so it was not needed. – willdanceforfun Mar 03 '16 at 11:38
  • Also, if dirname it's a large filesystem, problems with memory are evident. On my case with 1 millons of files, app needs ~512M ram on memory_limit. – abkrim Nov 22 '16 at 08:30
  • 2
    If you need the complete path like `/home/examples/banana.jpg` use `$fileinfo->getPathname()` – mgutt Mar 24 '17 at 08:33
  • 1
    You can use !$fileinfo->isDir() to avoid action on directories – LeChatNoir Apr 30 '17 at 08:45
  • How does this example work? Does "DirectoryIterator(dirname(__FILE__))" search the entire folder hierarchy on a server? If so isn't that going to perform super slow? – Eight Lives Apr 27 '22 at 03:02
51

If you don't have access to DirectoryIterator class try this:

<?php
$path = "/path/to/files";

if ($handle = opendir($path)) {
    while (false !== ($file = readdir($handle))) {
        if ('.' === $file) continue;
        if ('..' === $file) continue;

        // do something with the file
    }
    closedir($handle);
}
?>
NexusRex
  • 2,152
  • 17
  • 14
39

Use the scandir() function:

<?php
    $directory = '/path/to/files';

    if (!is_dir($directory)) {
        exit('Invalid diretory path');
    }

    $files = array();
    foreach (scandir($directory) as $file) {
        if ($file !== '.' && $file !== '..') {
            $files[] = $file;
        }
    }

    var_dump($files);
?>
Pere
  • 1,647
  • 3
  • 27
  • 52
ChorData
  • 523
  • 3
  • 4
23

You can also make use of FilesystemIterator. It requires even less code then DirectoryIterator, and automatically removes . and ...

// Let's traverse the images directory
$fileSystemIterator = new FilesystemIterator('images');

$entries = array();
foreach ($fileSystemIterator as $fileInfo){
    $entries[] = $fileInfo->getFilename();
}

var_dump($entries);

//OUTPUT
object(FilesystemIterator)[1]

array (size=14)
  0 => string 'aa[1].jpg' (length=9)
  1 => string 'Chrysanthemum.jpg' (length=17)
  2 => string 'Desert.jpg' (length=10)
  3 => string 'giphy_billclinton_sad.gif' (length=25)
  4 => string 'giphy_shut_your.gif' (length=19)
  5 => string 'Hydrangeas.jpg' (length=14)
  6 => string 'Jellyfish.jpg' (length=13)
  7 => string 'Koala.jpg' (length=9)
  8 => string 'Lighthouse.jpg' (length=14)
  9 => string 'Penguins.jpg' (length=12)
  10 => string 'pnggrad16rgb.png' (length=16)
  11 => string 'pnggrad16rgba.png' (length=17)
  12 => string 'pnggradHDrgba.png' (length=17)
  13 => string 'Tulips.jpg' (length=10)

Link: http://php.net/manual/en/class.filesystemiterator.php

Julian
  • 4,396
  • 5
  • 39
  • 51
6

You can use this code to loop through a directory recursively:

$path = "/home/myhome";
$rdi = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::KEY_AS_PATHNAME);
foreach (new RecursiveIteratorIterator($rdi, RecursiveIteratorIterator::SELF_FIRST) as $file => $info) {
    echo $file."\n";
}
Chris McFarland
  • 6,059
  • 5
  • 43
  • 63
GameScripting
  • 16,092
  • 13
  • 59
  • 98
4

glob() has provisions for sorting and pattern matching. Since the return value is an array, you can do most of everything else you need.

bcosca
  • 17,371
  • 5
  • 40
  • 51
  • 2
    This is good unless you are dealing with a lot of files... > 10,000. You'll run out of memory. – NexusRex Apr 11 '11 at 23:21
  • @NexusRex: You shouldn't be reading 10,000 records from a database either, but that's out of scope as far as the question is concerned – bcosca Apr 12 '11 at 02:25
  • Agreed! If reading from a database you can paginate with "limit" though—no such luck when you have a directory with 5 million XML files to iterate through. – NexusRex Apr 12 '11 at 05:15
  • There is SPL GlobIterator. – przemo_li Sep 05 '17 at 11:11
  • This is awesome for the correct use. In my case I want to purge the downloads folder each night for a small company website. I want to be able to have subdirectories in the downloads folder and this is the solution I was looking for. Thanks for posting! – Jon Vote Mar 26 '21 at 04:13
4

Most of the time I imagine you want to skip . and ... Here is that with recursion:

<?php

$rdi = new RecursiveDirectoryIterator('.', FilesystemIterator::SKIP_DOTS);
$rii = new RecursiveIteratorIterator($rdi);

foreach ($rii as $di) {
   echo $di->getFilename(), "\n";
}

https://php.net/class.recursivedirectoryiterator

Zombo
  • 1
  • 62
  • 391
  • 407
2

For completeness (since this seems to be a high-traffic page), let's not forget the good old dir() function:

$entries = [];
$d = dir("/"); // dir to scan
while (false !== ($entry = $d->read())) { // mind the strict bool check!
    if ($entry[0] == '.') continue; // ignore anything starting with a dot
    $entries[] = $entry;
}
$d->close();
sort($entries); // or whatever desired

print_r($entries);
Sz.
  • 3,342
  • 1
  • 30
  • 43
0

you can do this as well

$path = "/public";

$objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::SELF_FIRST);

foreach ($objects as $name => $object) {
  if ('.' === $object) continue;
  if ('..' === $object) continue;

str_replace('/public/', '/', $object->getPathname());

// for example : /public/admin/image.png => /admin/image.png
Masoud
  • 1,099
  • 1
  • 10
  • 22