PHP Developers Network

A community of PHP developers offering assistance, advice, discussion, and friendship.
 
Loading
It is currently Tue Apr 25, 2017 1:34 pm

All times are UTC - 5 hours




Post new topic Reply to topic  [ 23 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Recursive Directory Tree
PostPosted: Tue Apr 18, 2006 1:02 pm 
Offline
Tranquility In Moderation
User avatar

Joined: Sun Feb 06, 2005 8:18 pm
Posts: 5001
Location: Indiana
I noticed a couple people looking for directory trees lately. I came up with this function. The formatting gets messed up if it goes more than one level deep; but it does list the directories. :) I tried to get the formatting right but I couldn't get my brain around it.

Syntax: [ Download ] [ Hide ]
<?php
 
function dirList($directory,$padding=20,$level=1){
    $handle = opendir($directory);
    $ret = '';
   
    while (false !== ($file = readdir($handle))) {
        if(($file != '.') && ($file != '..')){
            if(is_dir($file)){
                $ret .= $file.'<p style="padding-left: '.$padding*$level.'px;">'.dirList($file).'</p>';
            } else {
                $ret .= $file.'<br />';
            }
        }
    }
    closedir($handle);
    return $ret;
}
 
echo dirList('./');
 
?>

_________________
Set Search Time - A google chrome extension. When you search only results from the past year (or set time period) are displayed. Helps tremendously when using new technologies to avoid outdated results.


Last edited by Weirdan on Sat May 03, 2008 7:31 am, edited 1 time in total.
php tags


Top
 Profile  
 
 Post subject:
PostPosted: Tue Apr 18, 2006 2:53 pm 
Offline
Neighborhood Spidermoddy
User avatar

Joined: Mon Mar 29, 2004 4:24 pm
Posts: 31559
Location: Bothell, Washington, USA
PHP 5.1.2 tested
Syntax: [ Download ] [ Hide ]
function DirTree(RecursiveDirectoryIterator $dir)
{
    $tree = array();
    $dirs = array(array($dir, &$tree));
   
    for($i = 0; $i < count($dirs); ++$i)
    {
        $d =& $dirs[$i][0];
        $tier =& $dirs[$i][1];
 
        for($d->rewind(); $d->valid(); $d->next())
        {
            if ($d->isDir())
            {
                $tier[$d->getFilename()] = array();
                $dirs[] = array($d->getChildren(), &$tier[$d->getFilename()]);
            }
            else
            {
                $tier[$d->getFilename()] = $d->getSize();
            }
        }
    }
   
    return $tree;
}
 
$dir = new RecursiveDirectoryIterator(getcwd());
$d = DirTree($dir);
var_export($d);
outputs (for SimpleTest's directory tree)
Syntax: [ Download ] [ Hide ]
array (
  'authentication.php' => 8332,
  'browser.php' => 38659,
  'collector.php' => 3464,
  'compatibility.php' => 6368,
  'cookies.php' => 13314,
  'detached.php' => 3169,
  'docs' =>
  array (
    'en' =>
    array (
      'authentication_documentation.html' => 12120,
      'browser_documentation.html' => 16006,
      'docs.css' => 1414,
      'expectation_documentation.html' => 13136,
      'form_testing_documentation.html' => 10478,
      'group_test_documentation.html' => 12240,
      'index.html' => 17681,
      'mock_objects_documentation.html' => 30541,
      'overview.html' => 18287,
      'partial_mocks_documentation.html' => 14570,
      'reporter_documentation.html' => 20732,
      'unit_test_documentation.html' => 14718,
      'web_tester_documentation.html' => 20339,
    ),
    'fr' =>
    array (
      'authentication_documentation.html' => 11429,
      'browser_documentation.html' => 17051,
      'docs.css' => 1414,
      'expectation_documentation.html' => 13822,
      'form_testing_documentation.html' => 10905,
      'group_test_documentation.html' => 12949,
      'index.html' => 18552,
      'mock_objects_documentation.html' => 31247,
      'overview.html' => 20230,
      'partial_mocks_documentation.html' => 16125,
      'reporter_documentation.html' => 21414,
      'server_stubs_documentation.html' => 15020,
      'unit_test_documentation.html' => 15243,
      'web_tester_documentation.html' => 21006,
    ),
  ),
  'dumper.php' => 16199,
  'encoding.php' => 15815,
  'errors.php' => 6215,
  'exceptions.php' => 1339,
  'expectation.php' => 25300,
  'extensions' =>
  array (
    'pear_test_case.php' => 6931,
    'phpunit_test_case.php' => 3137,
  ),
  'form.php' => 13003,
  'frames.php' => 20687,
  'HELP_MY_TESTS_DONT_WORK_ANYMORE' => 11726,
  'http.php' => 21694,
  'invoker.php' => 4079,
  'LICENSE' => 26421,
  'mock_objects.php' => 51679,
  'page.php' => 32449,
  'parser.php' => 28769,
  'README' => 4553,
  'reflection_php4.php' => 3326,
  'reflection_php5.php' => 9779,
  'remote.php' => 3855,
  'reporter.php' => 13256,
  'scorer.php' => 25079,
  'selector.php' => 3638,
  'shell_tester.php' => 10642,
  'simpletest.php' => 8930,
  'socket.php' => 7076,
  'tag.php' => 43475,
  'test' =>
  array (
    'acceptance_test.php' => 65863,
    'adapter_test.php' => 2129,
    'all_tests.php' => 551,
    'authentication_test.php' => 6192,
    'browser_test.php' => 37297,
    'collector_test.php' => 1788,
    'compatibility_test.php' => 3350,
    'cookies_test.php' => 10366,
    'detached_test.php' => 519,
    'dumper_test.php' => 3317,
    'encoding_test.php' => 7579,
    'errors_test.php' => 4443,
    'expectation_test.php' => 11560,
    'form_test.php' => 16619,
    'frames_test.php' => 22966,
    'http_test.php' => 20773,
    'interfaces_test.php' => 3142,
    'live_test.php' => 2015,
    'mock_objects_test.php' => 25165,
    'page_test.php' => 39037,
    'parser_test.php' => 24026,
    'parse_error_test.php' => 303,
    'reflection_php4_test.php' => 2029,
    'reflection_php5_test.php' => 5558,
    'remote_test.php' => 840,
    'shell_test.php' => 1285,
    'shell_tester_test.php' => 1455,
    'simpletest_test.php' => 416,
    'socket_test.php' => 827,
    'support' =>
    array (
      'collector' =>
      array (
        'collectable.1' => 0,
        'collectable.2' => 0,
      ),
      'latin1_sample' => 18,
      'spl_examples.php' => 401,
      'supplementary_upload_sample.txt' => 22,
      'upload_sample.txt' => 30,
    ),
    'tag_test.php' => 23566,
    'test_groups.php' => 3226,
    'test_with_parse_error.php' => 175,
    'unit_tester_test.php' => 1982,
    'unit_tests.php' => 484,
    'url_test.php' => 19210,
    'user_agent_test.php' => 15946,
    'visual_test.php' => 14621,
    'web_tester_test.php' => 7309,
    'xml_test.php' => 7675,
  ),
  'test_case.php' => 24683,
  'unit_tester.php' => 14777,
  'url.php' => 18608,
  'user_agent.php' => 12717,
  'VERSION' => 11,
  'web_tester.php' => 56837,
  'xml.php' => 20576,
)


Last edited by Weirdan on Sat May 03, 2008 7:31 am, edited 1 time in total.
php tags


Top
 Profile  
 
 Post subject:
PostPosted: Tue Apr 18, 2006 3:02 pm 
Offline
Neighborhood Spidermoddy
User avatar

Joined: Mon Mar 29, 2004 4:24 pm
Posts: 31559
Location: Bothell, Washington, USA
A version of the above compatible with PHP 4 producing the exact same output.
Syntax: [ Download ] [ Hide ]
function DirTree4($dir)
{
    $tree = array();
    $dirs = array(array($dir, &$tree));
   
    for($i = 0; $i < count($dirs); ++$i)
    {
        $d = opendir($dirs[$i][0]);
        $tier =& $dirs[$i][1];
 
        while($file = readdir($d))
        {
            if ($file != '.' and $file != '..')
            {
                $path = $dirs[$i][0] . DIRECTORY_SEPARATOR . $file;
                if (is_dir($path))
                {
                    $tier[$file] = array();
                    $dirs[] = array($path, &$tier[$file]);
                }
                else
                {
                    $tier[$file] = filesize($path);
                }
            }
        }
    }
   
    return $tree;
}
 
$d = DirTree4(getcwd());
var_export($d);


Last edited by Weirdan on Sat May 03, 2008 7:32 am, edited 1 time in total.
php tags


Top
 Profile  
 
 Post subject:
PostPosted: Tue Apr 18, 2006 3:18 pm 
Offline
Tranquility In Moderation
User avatar

Joined: Sun Feb 06, 2005 8:18 pm
Posts: 5001
Location: Indiana
Geez feyd owned me publicly :(

Just kidding. Those are very nice functions though.

_________________
Set Search Time - A google chrome extension. When you search only results from the past year (or set time period) are displayed. Helps tremendously when using new technologies to avoid outdated results.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Apr 18, 2006 3:35 pm 
Offline
Neighborhood Spidermoddy
User avatar

Joined: Mon Mar 29, 2004 4:24 pm
Posts: 31559
Location: Bothell, Washington, USA
The nice part: no recursion neccessary!


Top
 Profile  
 
 Post subject:
PostPosted: Sun Mar 04, 2007 12:20 am 
Offline
Forum Newbie

Joined: Sat Mar 03, 2007 2:42 pm
Posts: 1
feyd,

I think your iterative solution is very elegant! It utilizes a great use of references. Very cool. :-) I'm going to use the general algorithm if you don't mind... I'll make sure I give you credit.

It took me about 50 times looking over it to understand how the references work, but once I started getting it, I really liked the way you did things.

Take care,
cappaberra


Top
 Profile  
 
 Post subject:
PostPosted: Sun Mar 04, 2007 9:45 am 
Offline
Neighborhood Spidermoddy
User avatar

Joined: Mon Mar 29, 2004 4:24 pm
Posts: 31559
Location: Bothell, Washington, USA
cappaberra wrote:
feyd,

I think your iterative solution is very elegant! It utilizes a great use of references. Very cool. :-) I'm going to use the general algorithm if you don't mind... I'll make sure I give you credit.

It took me about 50 times looking over it to understand how the references work, but once I started getting it, I really liked the way you did things.

Take care,
cappaberra
I'm glad you enjoyed it. By all means, please do use it. I don't really care for the credit, but I'll take it. :)

My obsession with unraveling recursive structures stems from my days in C where the stack could very easily overflow quickly when recursing. Unwinding them takes a bit of creativity, I've yet to really find one I couldn't convert.

:)


Top
 Profile  
 
 Post subject:
PostPosted: Sun Mar 04, 2007 6:22 pm 
Offline
DevNet Master
User avatar

Joined: Mon Oct 25, 2004 9:29 pm
Posts: 3698
Location: New Jersey, US
Ooh, that's great. Definitely will be using this in my project.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 05, 2007 6:12 am 
Offline
DevNet Master
User avatar

Joined: Mon Sep 19, 2005 6:24 am
Posts: 3587
Location: London
I just spent 5mins oogling at that code, puzzled by how it will reach further than one level, finally realising that the $dirs array is updated by reference. Nice :) I will bear that practice in mind when I need to recursively search again in future. :)


Top
 Profile  
 
PostPosted: Thu Apr 26, 2007 5:33 pm 
Offline
Forum Newbie

Joined: Thu Apr 26, 2007 5:28 pm
Posts: 1
Just one small correction to the above code, to avoid directories named "0" from being considered the end of the directory.

Syntax: [ Download ] [ Hide ]
/* This is the correct way to loop over the directory. */
while (false !== ($file = readdir($handle))) {
    echo "$file\n";
}
 
/* This is the WRONG way to loop over the directory. */
while ($file = readdir($handle)) {
    echo "$file\n";
}


Top
 Profile  
 
 Post subject:
PostPosted: Thu May 24, 2007 5:44 am 
Offline
Forum Newbie

Joined: Wed May 23, 2007 7:12 am
Posts: 3
hello, my first post :D

i was looking for a directory tree to use it online, but i didn't find any implementation that would also print a link to the file
so i made one :)

you can see it here:
http://www.streamkid.de/~alex/?cat=stuff

Syntax: [ Download ] [ Hide ]
 
/* you call the function like this:
$img = array ('images');
ldir('images/', 0, 0, $img, 'images');
this will print the contents of directory images */

        function ldir($path, $level, $m, $struct, $abs) {
                $ignore = array ('cgi-bin', '.', '..', '.htaccess', '.t3hdirectives');
                $dh = @opendir($path);
                while (false !== ($file = readdir($dh))) {
                        if (!in_array($file, $ignore)) {
                                $spaces = str_repeat('&nbsp;', ($level*4));
                                $struct[$level] = $abs;
                                $url = '';
                                if ($level > 0) {
                                        for ($i = 0; $i <= $level; $i += 1) {
                                                $url .= $struct[$i];
                                                $url .= '/';
                                            }
                                        $url .= $file;
                                    }
                                else {
                                        $url .= $abs;
                                        $url .= '/';
                                        $url .= $file;
                                    }
                                if (is_dir("$path/$file")) {
                                        echo "<a title=\"This is a directory. Nothing to link to.\">$spaces $file</a>&nbsp;<i>(dir)</i><br/>";
                                        $dir .= '/';
                                        $dir .= $file;
                                        ldir ("$path/$file", ($level + 1), $m, $struct, $file);
                                    }
                                else {
                                        switch ($m) {
                                                case 0: echo "<a href=\"?cat=stuff&amp;img=$url\">$spaces $file</a><br/>"; break;
                                                case 1: echo "<a href=\"$url\">$spaces $file</a><br/>";             break;
                                                case 2: echo "<a href=\"$url\">$spaces $file</a><br/>";                break;
                                            }
                                    }
                            }
                    }
                closedir($dh);
            }
/* you can completely delete $m and the switch statement, i just used it because depending on the type the url differs */
 


i just started learning php, so your comments on the code are more than welcome :)


Last edited by Weirdan on Sat May 03, 2008 7:34 am, edited 1 time in total.
php tags


Top
 Profile  
 
 Post subject:
PostPosted: Thu May 24, 2007 6:44 am 
Offline
Jedi Mod
User avatar

Joined: Tue Dec 21, 2004 6:03 pm
Posts: 5263
Location: usrlab.com
2 comments:

1. Never use the @ symbol to suppress errors. Write your code so that it evaluates the return from a function call and acts accordingly.

2. Personally I'd fetch the directory structure into an array and then pass that to a function (or an object) that builds an HTML view of it with the necessary links. Separating the logic of scanning a file system and displaying the HTML will lead to a more maintainable project in the long term.


Top
 Profile  
 
 Post subject:
PostPosted: Thu May 24, 2007 8:27 am 
Offline
Forum Newbie

Joined: Wed May 23, 2007 7:12 am
Posts: 3
Thanks for commenting:)
About (2): Perhaps I will do that on v2 ;p
I guess its more difficult to be coded, so I want to gain some more expierence first and then refactor the thing :)


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jun 14, 2007 8:15 am 
Offline
Forum Regular

Joined: Wed Dec 13, 2006 11:28 am
Posts: 575
I love SPL

This snippet will recursively list all the folders and files in the specified path.

Syntax: [ Download ] [ Hide ]
 
$it = new RecursiveDirectoryIterator('/path/to/list');
foreach(new RecursiveIteratorIterator($it, RecursiveIteratorIterator::SELF_FIRST) as $file)
{
    echo $file ;       
}
 



$file is an splFileInfo object that uses __toString() for the echo above. You can also use the following methods.

Syntax: [ Download ] [ Hide ]
 
        echo "File name = " . $file->getFilename() . "\n";
        echo "Path name = " . $file->getPathname() . "\n";
        echo "Permission = " . $file->getPerms() . "\n";
        echo "Inod = " . $file->getInode() . "\n";
        echo "Size = " . $file->getSize() . "\n";
        echo "Owner = " . $file->getOwner() . "\n";
        echo "Group = " . $file->getGroup() . "\n";
        echo "Atime = " . $file->getATime() . "\n";
        echo "Mtime = " . $file->getMTime() . "\n";
        echo "CTime = " . $file->getCTime() . "\n";
        echo "Type = " . $file->getType() . "\n";
        echo "Writable = " . $file->isWritable() . "\n";
        echo "Readable = " . $file->isReadable() . "\n";
        echo "Executable = " . $file->isExecutable() . "\n";
        echo "Is file = " . $file->isFile() . "\n";
        echo "Is directory = " . $file->isDir() . "\n";
        echo "Is link = " . $file->isLink() . "\n";
        echo "Is dot = " . $file->isDot() . "\n";
        echo "To string = " . $file->__toString() . "\n";
 


To create an indented list you could explode the path on the directory separator then subtract from the the number depth of your search path. That would be how far to indent your files.


Last edited by Weirdan on Sat May 03, 2008 7:34 am, edited 1 time in total.
php tags


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 27, 2007 6:15 am 
Offline
Forum Contributor

Joined: Wed Jun 13, 2007 5:07 am
Posts: 109
feyd wrote:
PHP 5.1.2 tested
Syntax: [ Download ] [ Hide ]
function DirTree(RecursiveDirectoryIterator $dir)
{
    $tree = array();
    $dirs = array(array($dir, &$tree));
   
    for($i = 0; $i < count($dirs); ++$i)
    {
        $d =& $dirs[$i][0];
        $tier =& $dirs[$i][1];
 
        for($d->rewind(); $d->valid(); $d->next())
        {
            if ($d->isDir())
            {
                $tier[$d->getFilename()] = array();
                $dirs[] = array($d->getChildren(), &$tier[$d->getFilename()]);
            }
            else
            {
                $tier[$d->getFilename()] = $d->getSize();
            }
        }
    }
   
    return $tree;
}
 
$dir = new RecursiveDirectoryIterator(getcwd());
$d = DirTree($dir);
var_export($d);
outputs (for SimpleTest's directory tree)
Syntax: [ Download ] [ Hide ]
array (
  'authentication.php' => 8332,
  'browser.php' => 38659,
  'collector.php' => 3464,
  'compatibility.php' => 6368,
  'cookies.php' => 13314,
  'detached.php' => 3169,
  'docs' =>
  array (
    'en' =>
    array (
      'authentication_documentation.html' => 12120,
      'browser_documentation.html' => 16006,
      'docs.css' => 1414,
      'expectation_documentation.html' => 13136,
      'form_testing_documentation.html' => 10478,
      'group_test_documentation.html' => 12240,
      'index.html' => 17681,
      'mock_objects_documentation.html' => 30541,
      'overview.html' => 18287,
      'partial_mocks_documentation.html' => 14570,
      'reporter_documentation.html' => 20732,
      'unit_test_documentation.html' => 14718,
      'web_tester_documentation.html' => 20339,
    ),
    'fr' =>
    array (
      'authentication_documentation.html' => 11429,
      'browser_documentation.html' => 17051,
      'docs.css' => 1414,
      'expectation_documentation.html' => 13822,
      'form_testing_documentation.html' => 10905,
      'group_test_documentation.html' => 12949,
      'index.html' => 18552,
      'mock_objects_documentation.html' => 31247,
      'overview.html' => 20230,
      'partial_mocks_documentation.html' => 16125,
      'reporter_documentation.html' => 21414,
      'server_stubs_documentation.html' => 15020,
      'unit_test_documentation.html' => 15243,
      'web_tester_documentation.html' => 21006,
    ),
  ),
  'dumper.php' => 16199,
  'encoding.php' => 15815,
  'errors.php' => 6215,
  'exceptions.php' => 1339,
  'expectation.php' => 25300,
  'extensions' =>
  array (
    'pear_test_case.php' => 6931,
    'phpunit_test_case.php' => 3137,
  ),
  'form.php' => 13003,
  'frames.php' => 20687,
  'HELP_MY_TESTS_DONT_WORK_ANYMORE' => 11726,
  'http.php' => 21694,
  'invoker.php' => 4079,
  'LICENSE' => 26421,
  'mock_objects.php' => 51679,
  'page.php' => 32449,
  'parser.php' => 28769,
  'README' => 4553,
  'reflection_php4.php' => 3326,
  'reflection_php5.php' => 9779,
  'remote.php' => 3855,
  'reporter.php' => 13256,
  'scorer.php' => 25079,
  'selector.php' => 3638,
  'shell_tester.php' => 10642,
  'simpletest.php' => 8930,
  'socket.php' => 7076,
  'tag.php' => 43475,
  'test' =>
  array (
    'acceptance_test.php' => 65863,
    'adapter_test.php' => 2129,
    'all_tests.php' => 551,
    'authentication_test.php' => 6192,
    'browser_test.php' => 37297,
    'collector_test.php' => 1788,
    'compatibility_test.php' => 3350,
    'cookies_test.php' => 10366,
    'detached_test.php' => 519,
    'dumper_test.php' => 3317,
    'encoding_test.php' => 7579,
    'errors_test.php' => 4443,
    'expectation_test.php' => 11560,
    'form_test.php' => 16619,
    'frames_test.php' => 22966,
    'http_test.php' => 20773,
    'interfaces_test.php' => 3142,
    'live_test.php' => 2015,
    'mock_objects_test.php' => 25165,
    'page_test.php' => 39037,
    'parser_test.php' => 24026,
    'parse_error_test.php' => 303,
    'reflection_php4_test.php' => 2029,
    'reflection_php5_test.php' => 5558,
    'remote_test.php' => 840,
    'shell_test.php' => 1285,
    'shell_tester_test.php' => 1455,
    'simpletest_test.php' => 416,
    'socket_test.php' => 827,
    'support' =>
    array (
      'collector' =>
      array (
        'collectable.1' => 0,
        'collectable.2' => 0,
      ),
      'latin1_sample' => 18,
      'spl_examples.php' => 401,
      'supplementary_upload_sample.txt' => 22,
      'upload_sample.txt' => 30,
    ),
    'tag_test.php' => 23566,
    'test_groups.php' => 3226,
    'test_with_parse_error.php' => 175,
    'unit_tester_test.php' => 1982,
    'unit_tests.php' => 484,
    'url_test.php' => 19210,
    'user_agent_test.php' => 15946,
    'visual_test.php' => 14621,
    'web_tester_test.php' => 7309,
    'xml_test.php' => 7675,
  ),
  'test_case.php' => 24683,
  'unit_tester.php' => 14777,
  'url.php' => 18608,
  'user_agent.php' => 12717,
  'VERSION' => 11,
  'web_tester.php' => 56837,
  'xml.php' => 20576,
)





Hey really a nice script Feyd... now how do we convert this PHP code into HTML i.e, how are we supposed to change the raw code in a tree like HTML structure?


Last edited by Weirdan on Sat May 03, 2008 7:35 am, edited 1 time in total.
php tags


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 23 posts ]  Go to page 1, 2  Next

All times are UTC - 5 hours


Who is online

Users browsing this forum: No registered users and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Jump to:  
Powered by phpBB® Forum Software © phpBB Group