1

So I've been trying to create a recursive file directory tree listing function. I have most of it except some bugs. Such as duplicate directory names because of the code as well as it is not going deep enough in the tree.

function ftpFileList($ftpConnection, $path="/") {
    static $allFiles = array();
    $contents = ftp_nlist($ftpConnection, $path);
    foreach($contents as $currentFile) {
        if($currentFile !== "." && $currentFile !== ".."){
          if( strpos($currentFile,".") === false || strpos($currentFile,"." === 0) ) {
            if(!$allFiles[$path][$currentFile]){
                 $allFiles[$path][$currentFile] = array();
            }
            ftpFileList($ftpConnection,$currentFile);
         }else{
             if($currentPath !== "." && $currentPath !== "..") $allFiles[$path][] = $currentFile;
         }
      } 
   }
   return $allFiles;
}

The returned array looks similar to this

array(3) {
  [""]=>
      array(4) {
       [0]=>
        string(9) ".ftpquota"
       [1]=>
        string(9) ".htaccess"
       ["kms"]=>
        array(0) {
        }
       ["public_html"]=>
        array(0) {
        }
       }
  ["kms"]=>
     array(6) {
      [0]=>
       string(16) "admin_config.php"
      [1]=>
       string(8) "css.json"
      [2]=>
       string(10) "pages.json"
      ["php_includes"]=>
       array(0) {
       }
     ["site"]=>
       array(0) {
       }
     ["templates"]=>
       array(0) {
       }
      }
 ["public_html"]=>
   array(20) {
   [0]=>
    string(9) ".htaccess"
   [1]=>
    string(7) "404.php"
   ...
  }
}

Basically what I want to do is get something like this

.htaccess
.ftpquota
 -public_html
  -folder2
   -folder3
     file.ext
  file2.ext
 -kms
  -folder4
   file3.ext
   -folder5
    -file4.ext
   file5.ext

Hopefully you can understand what I am asking, just need to see what is wrong here, and how to get the correct index to place the $currentFile in because of the fact that it's search for $allFiles[$path][$currentFile] which won't be correct. anyways just need a good recursive function to list all files in an array, directories are indexes.

EasyBB
  • 6,176
  • 9
  • 47
  • 77
  • possible duplicate of http://stackoverflow.com/questions/952263/deep-recursive-array-of-directory-structure-in-php – Jonathan Nov 08 '14 at 19:40
  • 1
    @Jonathan - is it a little bit different because it's for a remote server. Some function has to be implemented to see if a remote directory item is a subfolder or a file. Manual on ftp_nlist has some examples http://php.net/manual/ru/function.ftp-nlist.php – Timothy Ha Nov 08 '14 at 19:58
  • '/path/to/root/' in the linked answer can be a stream (eg ftp) it doesn't have to be in any specific physical location – Jonathan Nov 08 '14 at 20:12

2 Answers2

2

I don't think there's any reason the "$allFiles" variable should be static.

Also, you're using a $currentPath variable that isn't defined anywhere. What were you trying to achieve with that variable?

Try this code instead (it probably still isn't perfect, but should give you enough hint on how to make real recursion):

function ftpFileList($ftpConnection, $path="/") {
    $files = array();
    $contents = ftp_nlist($ftpConnection, $path);
    foreach($contents as $currentFile) {
        if($currentFile !== "." && $currentFile !== ".."){
          if( strpos($currentFile,".") === false || strpos($currentFile,"." === 0) ) {
            $files[$path][$currentFile] = ftpFileList($ftpConnection, $path.$currentFile.'/');
         }else{
             if($currentPath !== "." && $currentPath !== "..")
                 $files[$path][] = $currentFile;
         }
      } 
   }
   return $files;
}
Maxime
  • 388
  • 3
  • 10
  • How do you recognize a remote folder (to dive into)? As I understand, ftp_nlist returns only a plain list. – Timothy Ha Nov 08 '14 at 19:56
  • I'm checking the string for a . In it if it does it's a file else it's a folder. There's more testing and what not but just trying to fix my recursion right now. I'll check this when I get back to my computer thanks for quick response – EasyBB Nov 08 '14 at 20:02
  • 1
    I'm relying on the OP logic to decide if it's a file or a folder. I'm not saying that it works in all cases (it doesn't), I'm just reusing the OP code for that part (which isn't the priamary focus of the question anyway). – Maxime Nov 08 '14 at 20:07
  • Exactly my focus is the recursion and return val – EasyBB Nov 08 '14 at 20:21
  • This works wonderfully, just need to debug it a little but almost perfect so this is my accepted answer. thanks Maxime – EasyBB Nov 08 '14 at 22:19
1

Expanding on the answer linked in my comment, you can use DirectoryIterator in combination with the ftp:// stream wrapper

$fileData = fillArrayWithFileNodes( new DirectoryIterator( 'ftp://path/to/root' ) );

function fillArrayWithFileNodes( DirectoryIterator $dir )
{
  $data = array();
  foreach ( $dir as $node )
  {
    if ( $node->isDir() && !$node->isDot() )
    {
      $data[$node->getFilename()] = fillArrayWithFileNodes( new DirectoryIterator( $node->getPathname() ) );
    }
    else if ( $node->isFile() )
    {
      $data[] = $node->getFilename();
    }
  }
  return $data;
}
Jonathan
  • 1,542
  • 3
  • 16
  • 24
  • I need to expand this to not use DirectoryIterator as some people may not have it since it was added to PHP5. Some may still use older version, who I don't know but there is always that one person. – EasyBB Nov 08 '14 at 22:17
  • php5 was released 10 years ago – Jonathan Nov 09 '14 at 02:22