# Listing all directories, sub directories and files starting from the root

I have to deploy this code that will list all the directories, sub directories and files in it starting from the root. The code works but I am not sure if this is the correct way to list. It should not fail, though.

Also, in despite not allowing directories with the name . and .., they get printed. Why is that?

<?php

# Snippet that lists all the directories,sub directories and files under that directory
# recursive function

function directory_f_lister($root) {$dir_list = scandir($root); for($var=0;$var<count($dir_list);$var++) { if(is_readable($root.$dir_list[$var])) {
if(is_dir($root.$dir_list[$var])) { if($dir_list[$var] === "." ||$dir_list[$var] === "..") continue; echo "<h3>Name of directory$dir_list[$var]</h3>"; echo "<br />";$dh = opendir($root.$dir_list[$var]); while(($name = readdir($dh)) !== false) { if(is_dir($root.$dir_list[$var].$name)) { if($dir_list[$var] === "." ||$dir_list[$var] === "..") continue; echo "Name of directory : <strong>$name </strong>";
echo "<br />";
directory_f_lister($root.$dir_list[$var].$name);
}else {
echo $name; echo "<br/>"; } } } } } } directory_f_lister(DIRECTORY_SEPARATOR); #end  ## 2 Answers well . and .. are not directories, thats are navigationpoints of directories, . means go inside a root directory, .. means go one folder back, you might noticed this already in includes like include ../../../foo/bar.php also instead of scandir and readdir php has classes for this purpose DirectoryIterator or FileSystemIterator And if you wish to create reusable methods, dont do output there, instead return an array of folders/files something like $directories = scanDirectories($rootDirectory); //create output array foreach($directories as $directory){ echo$directory.'<br/>';
}


this allowes you to modify the output without editing the sourcecode, you could also wrap the output within a function e.g. viewDirectories and reuse it on different places.

here is a small Example

    ini_set('html_errors', 'On');

function scanDirectory($path) {$path = realpath($path); return new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::SELF_FIRST);

}

foreach(scanDirectory('./') as $name=>$object){

echo $name.'<br/>'; }  About your question: $root.$dir_list[$var].$name //this is your directory name  but youre checking if this name is . and .. $dir_list[$var]  so its never becomes true 1. If you invert your if condition and continue with next loop entry then you can reduce your level of nesting. 2. You will currently miss all files in the first $root (due do the outer is_dir condition).
3. You should be able move the recursion further to the top. The shorted algorithm for recursively listing directories goes like this (pseudo code):

func list(root)
print "Directory: " + root
foreach (entry in contentof(root))
if (entry is directory)
list(entry)
else
print "File: " + entry


In your code that could look something like this:

function directory_f_lister($root) { echo "<h3>Name of directory:$root</h3>";
echo "<br>";
for (scandir($root) as$current)
{
$currentFullPath =$root.$current; if (!is_readable($currentFullPath) || $current == "." ||$current == "..")
continue;
if (is_dir($currentFullPath)) { list($currentFullPath);
}
else
{
echo \$current;
echo "<br>";
}
}
}

4. Your approach intermingles the iteration of the structure (filesystem) with the actions of what to do for each item (printing). A better way would be to simply use the DirectoryIterator to iterate over the filesystem and print each item.