13

Possible Duplicate:
PHP Get all subdirectories of a given directory

I want a drop down menu to show all sub-directories in ./files/$userid/ not just the main folder. For example: /files/$userid/folder1/folder2/

My current code is:

HTML:

<select name="myDirs">
<option value=""  selected="selected">Select a folder</option>

PHP:

if (chdir("./files/" . $userid)) {

       $dirs = glob('*', GLOB_ONLYDIR);
       foreach($dirs as $val){
          echo '<option value="'.$val.'">'.$val."</option>\n";
       }        
        } else {
       echo 'Changing directory failed.';
}
Community
  • 1
  • 1
Brian
  • 1,951
  • 16
  • 56
  • 101
  • And your question is? Keep in mind that formulating requirements is not a programming question. I suggest you search for your requirements on site first, because listing directories has been asked and answered in various flavors already. [So why not take a place at the bar and order your drink?](http://stackoverflow.com/search) – hakre Jan 13 '13 at 15:36
  • You will need to use PHP's native [RecursiveDirectoryIterator](http://php.net/manual/en/class.recursivedirectoryiterator.php) class. [This answer](http://stackoverflow.com/a/2398163/427992) should help. – hohner Jan 13 '13 at 15:37
  • I tried this http://pastebin.com/fpJiiCbZ, but it doesn't work. This is the output I get: http://i.imgur.com/gWt3U.png – Brian Jan 13 '13 at 15:47
  • You didn't implement the correct code. Copy and paste the PHP code set out in the above answer and it should work. – hohner Jan 13 '13 at 15:49
  • I did, I don't want to get filenames, only folders. What's 'work.txt' in the answer? (Copy pasting the code return empty drop-down) – Brian Jan 13 '13 at 15:54
  • So Ok, I did as you told me, with little modifications, and it's working. However I would like to ask a question. Drop down values are being listed, for example /files/14/blabla are being displayed more than once. Why is this? Here's a screenshot to get the idea.. Code: http://pastebin.com/cGKRkJzn Image: http://i.imgur.com/8HY8a.png . Is there a method how to supress the root folder from being shown? – Brian Jan 13 '13 at 16:08
  • Inside every directory there are two (pseudo) files called `.` and `..`. If you look carefully, your script is showing them. To omit them, use `!$file->isDot()` in your if statement. – hohner Jan 13 '13 at 16:49
  • @Jamie That returns an empty drop box. I did `if($file->isDir() && !$file->isDot() ) { .. }` – Brian Jan 14 '13 at 13:46
  • @Jamie Nevermind, used RecursiveDirectoryIterator::SKIP_DOTS. – Brian Jan 14 '13 at 13:50

3 Answers3

53

RecursiveDirectoryIterator should do the trick. Unfortunately, the documentation is not great, so here is an example:

$root = '/etc';

$iter = new RecursiveIteratorIterator(
    new RecursiveDirectoryIterator($root, RecursiveDirectoryIterator::SKIP_DOTS),
    RecursiveIteratorIterator::SELF_FIRST,
    RecursiveIteratorIterator::CATCH_GET_CHILD // Ignore "Permission denied"
);

$paths = array($root);
foreach ($iter as $path => $dir) {
    if ($dir->isDir()) {
        $paths[] = $path;
    }
}

print_r($paths);

This generates the following output on my computer:

Array
(
    [0] => /etc
    [1] => /etc/rc2.d
    [2] => /etc/luarocks
    ...
    [17] => /etc/php5
    [18] => /etc/php5/apache2
    [19] => /etc/php5/apache2/conf.d
    [20] => /etc/php5/mods-available
    [21] => /etc/php5/conf.d
    [22] => /etc/php5/cli
    [23] => /etc/php5/cli/conf.d
    [24] => /etc/rc4.d
    [25] => /etc/minicom
    [26] => /etc/ufw
    [27] => /etc/ufw/applications.d
    ...
    [391] => /etc/firefox
    [392] => /etc/firefox/pref
    [393] => /etc/cron.d
)
PleaseStand
  • 31,641
  • 6
  • 68
  • 95
  • thanks @PleaseStand its work fine, only need one more foreach loop for list view like your output – asi_x May 26 '15 at 19:24
  • Nice one. It would be better if you can illustrate how to filter away hidden folders & their contents (such as `.svn`). – Raptor Nov 16 '15 at 08:22
  • doesn't work for me... just timeouts even on timeout set to one hour when directory count is only 1000 – Flash Thunder Dec 01 '17 at 23:40
13

You can write your own recursive listing of the directories like:

function expandDirectories($base_dir) {
      $directories = array();
      foreach(scandir($base_dir) as $file) {
            if($file == '.' || $file == '..') continue;
            $dir = $base_dir.DIRECTORY_SEPARATOR.$file;
            if(is_dir($dir)) {
                $directories []= $dir;
                $directories = array_merge($directories, expandDirectories($dir));
            }
      }
      return $directories;
}

$directories = expandDirectories(dirname(__FILE__));
print_r($directories);
unused
  • 796
  • 4
  • 12
3

You can use a recursive glob implementation like in this function:

function rglob($pattern='*', $path='', $flags = 0) {
$paths=glob($path.'*', GLOB_MARK|GLOB_ONLYDIR|GLOB_NOSORT);
$files=glob($path.$pattern, $flags);
foreach ($paths as $path) {
  $files=array_merge($files,rglob($pattern, $path, $flags));
}
return $files;
}
Alex
  • 341
  • 3
  • 7