Directory files scanner with sorting.

Coding Critique is the place to post source code for peer review by other members of DevNetwork. Any kind of code can be posted. Code posted does not have to be limited to PHP. All members are invited to contribute constructive criticism with the goal of improving the code. Posted code should include some background information about it and what areas you specifically would like help with.

Popular code excerpts may be moved to "Code Snippets" by the moderators.

Moderator: General Moderators

User avatar
onion2k
Jedi Mod
Posts: 5263
Joined: Tue Dec 21, 2004 5:03 pm
Location: usrlab.com

Directory files scanner with sorting.

Post by onion2k »

I ought to make this into an object or something really.

Code: Select all

	function getFiles($path,$level=0) {

		static $arrIgnoreDirectories = array("directory1","directory2");
		static $arrIgnoreFiles = array("topSecretFile.txt");
		static $arrAllowedExtensions = array("php","txt");
		
		if (is_dir($path)) {
			if ($dh = opendir($path)) {
				while (($file = readdir($dh)) !== false) {
					$fullpath = $path."/".$file;
					if ($file == "." || $file == "..") continue;
					if ((in_array($file,$arrIgnoreDirectories) and is_dir($fullpath)) or (in_array($file,$arrIgnoreFiles) and !is_dir($fullpath))) continue;
					if (!in_array(fileExtension($file),$arrAllowedExtensions) and !is_dir($fullpath)) continue;
					$a = stat($fullpath);
					$files[$fullpath]['size'] = (is_dir($fullpath)) ? 0 : $a['size'];
					$files[$fullpath]['name'] = $file;
					$files[$fullpath]['type'] = filetype($fullpath);
					$files[$fullpath]['hash'] = (is_dir($fullpath)) ? "" : md5_file($fullpath);
					$files[$fullpath]['mtime'] = $a['mtime'];
					$files[$fullpath]['level'] = $level;
					if (is_dir($fullpath)) {
						getFiles($fullpath,$level+1);
					}
				}
				closedir($dh);
			}
		}
		
		return $files;
		
	}
	
	function fileExtension($file) {
		return substr($file,strrpos($file,".")+1);
	}

	function sortby_date_asc($ar1, $ar2) {
		if ($ar1['mtime']<$ar2['mtime']) { return -1; } elseif ($ar1['mtime']>$ar2['mtime']) { return 1; }
		return 0;
	}

	function sortby_date_desc($ar1, $ar2) {
		if ($ar1['mtime']<$ar2['mtime']) { return 1; } elseif ($ar1['mtime']>$ar2['mtime']) { return -1; }
		return 0;
	}

	function sortby_name_asc($ar1, $ar2) {
		if ($ar1['name']<$ar2['name']) { return -1; } elseif ($ar1['name']>$ar2['name']) { return 1; }
		return 0;
	}

	function sortby_name_desc($ar1, $ar2) {
		if ($ar1['name']<$ar2['name']) { return 1; } elseif ($ar1['name']>$ar2['name']) { return -1; }
		return 0;
	}

	function sortby_size_asc($ar1, $ar2) {
		if ($ar1['size']<$ar2['size']) { return -1; } elseif ($ar1['size']>$ar2['size']) { return 1; }
		return 0;
	}

	function sortby_size_desc($ar1, $ar2) {
		if ($ar1['size']<$ar2['size']) { return 1; } elseif ($ar1['size']>$ar2['size']) { return -1; }
		return 0;
	}
To use it just call getFiles() and then uasort() the returned array. Eg:

Code: Select all

	$files = getFiles("myDirectory");
	
	foreach($files as $file => $data) {
		echo $data['name']." - ".date("d/m/Y H:i:s",$data['mtime'])."<br>";
	}
	
	echo "<br><br>";
	uasort($files, 'sortby_date_asc');

	foreach($files as $file => $data) {
		echo $data['name']." - ".date("d/m/Y H:i:s",$data['mtime'])."<br>";
	}
Change the second argument in uasort to one of the six functions I've given to change the sorting, eg sortby_date_asc, sortby_date_desc, sortby_name_asc, sortby_name_desc, sortby_size_asc, sortby_size_desc.

Comments appreciated.
User avatar
Oren
DevNet Resident
Posts: 1640
Joined: Fri Apr 07, 2006 5:13 am
Location: Israel

Post by Oren »

It's pretty much basic... Why would someone use/need it?

Edit: glob(), scandir(), anyone?
User avatar
John Cartwright
Site Admin
Posts: 11470
Joined: Tue Dec 23, 2003 2:10 am
Location: Toronto
Contact:

Post by John Cartwright »

Might want to take a look at this snipplet posted by feyd. Nice way of making a directory tree without recursion.
jleampark
Forum Newbie
Posts: 16
Joined: Wed Jul 27, 2005 6:46 am

Post by jleampark »

That is a beautiful piece of code.

Pat yourself on the back and give yourself the rest of the day off. And if anyone questions you, tell them to take it up with me.

:wink:

Oren said, "It's pretty much basic... Why would someone use/need it?"

To which I answer, " 'cause some of us are basic."
User avatar
onion2k
Jedi Mod
Posts: 5263
Joined: Tue Dec 21, 2004 5:03 pm
Location: usrlab.com

Post by onion2k »

Oren wrote:It's pretty much basic... Why would someone use/need it?

Edit: glob(), scandir(), anyone?
I needed something to build a sortable array from a filesystem, and at the same time limit it to certain file extensions and ignore certain subdirectories and files. It's basic, but useful. If someone wants to suggest a way of doing it that's better/quicker/smarter I'm all ears.

EDIT: Also, scandir() is PHP 5. I wrote this thing for a PHP 4 application.
User avatar
Oren
DevNet Resident
Posts: 1640
Joined: Fri Apr 07, 2006 5:13 am
Location: Israel

Post by Oren »

Jcart wrote:Nice way of making a directory tree without recursion.
It does use recursion as far as I can see :P

onion2k, I see - nice argument :P
We really should stop supporting PHP4... c'mon, PHP5 has been here since 2004!
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

Oren wrote:
Jcart wrote:Nice way of making a directory tree without recursion.
It does use recursion as far as I can see :P
I'm pretty sure Jcart was referring to my snippet in the thread he linked, which does not use recursion in both the PHP 5 and PHP 4 versions posted.
User avatar
infolock
DevNet Resident
Posts: 1708
Joined: Wed Sep 25, 2002 7:47 pm

Post by infolock »

Oren wrote:
Jcart wrote:Nice way of making a directory tree without recursion.
It does use recursion as far as I can see :P

onion2k, I see - nice argument :P
We really should stop supporting PHP4... c'mon, PHP5 has been here since 2004!
As much as I'd like to agree, I must say I'm still using php 4, and it's not by choice. Most companies I work with are still on the php 4 bandwagon and it's because so much of their code has to be rewritten to work with php 5's corrected needle/haystack, mysql functions, and other misc upgrades that came with 5. I know php 5 is backwards compatable, but it's only if you choose the enviornment to run in only 4, leaving you without 5 functionality. And what's worse is that as long as 4 and 5 have such problems, it's going to make development for those clients even harder when they are using 4. The only solution would be to use 2 versions of php on the same server, and then slowly phase out the 4 applications and go through a rewrite/upgrade process, which most companiies don't want/can't do t.

Sorry, I know I'm taking this argument off-topic, but I keep hearing things like this all the time, and figured I'd at least give a more "open minded" approach as to why it's harder to phase out 4, kind of like it was when phasing out php 3 was on everyone's plate.
User avatar
RobertGonzalez
Site Administrator
Posts: 14293
Joined: Tue Sep 09, 2003 6:04 pm
Location: Fremont, CA, USA

Post by RobertGonzalez »

Dude, I have never seen feyd's snippet before. That thing is so awesome. I am already tweaking it for my needs. Very nice.
User avatar
Oren
DevNet Resident
Posts: 1640
Joined: Fri Apr 07, 2006 5:13 am
Location: Israel

Post by Oren »

feyd wrote:I'm pretty sure Jcart was referring to my snippet in the thread he linked, which does not use recursion in both the PHP 5 and PHP 4 versions posted.
Oh ok... I see, cool 8)

infolock, yes I agree with you. I believe there are 2 main reasons why we still use PHP4:

1. The reason you mentioned.
2. Webhosts.

Now, I must say that they are both, together, act like some non-ending cycle where each one triggers the other. This also explains why PHP4 is still around even after 2-3 years from the first release of PHP5 :cry: :? :x
User avatar
RobertGonzalez
Site Administrator
Posts: 14293
Joined: Tue Sep 09, 2003 6:04 pm
Location: Fremont, CA, USA

Post by RobertGonzalez »

2 words: Dedicates servers. Cost a little more, but well worth it to run PHP5 and MySQL 5+.
User avatar
Kieran Huggins
DevNet Master
Posts: 3635
Joined: Wed Dec 06, 2006 4:14 pm
Location: Toronto, Canada
Contact:

Post by Kieran Huggins »

another word: dreamhost - has php4, 5 AND MySQL 5... and it's CHEAP
User avatar
Jenk
DevNet Master
Posts: 3587
Joined: Mon Sep 19, 2005 6:24 am
Location: London

Post by Jenk »

for UK/Euro residents, tsohost.co.uk offer both php4 and php5 with mysql5.
User avatar
RobertGonzalez
Site Administrator
Posts: 14293
Joined: Tue Sep 09, 2003 6:04 pm
Location: Fremont, CA, USA

Post by RobertGonzalez »

Sorry guys. I derailed this thread talking about servers and hosting, which have nothing to do with the original context of the thread.

// slaps self for being a derailer

Now lets get back on topic. What say you?
jleampark
Forum Newbie
Posts: 16
Joined: Wed Jul 27, 2005 6:46 am

Post by jleampark »

onion2K,

I grabbed your code (referenced at top of thread) and tweaked it a bit for my conditions and it works great.

One little problem that I need solved...

First, here's the code:

Code: Select all

<?php 		
        function getFiles($path,$level=0) { 

                static $arrIgnoreDirectories = array("../esmpd_minutes"); 
                static $arrIgnoreFiles = array("topSecretFile.txt"); 
                static $arrAllowedExtensions = array("doc","wpd"); 
                
                if (is_dir($path)) { 
                        if ($dh = opendir($path)) { 
                                while (($file = readdir($dh)) !== false) { 
                                        $fullpath = $path."/".$file; 
                                        if ($file == "." || $file == "..") continue; 
                                        if ((in_array($file,$arrIgnoreDirectories) and is_dir($fullpath)) or (in_array($file,$arrIgnoreFiles) and !is_dir($fullpath))) continue; 
                                        if (!in_array(fileExtension($file),$arrAllowedExtensions) and !is_dir($fullpath)) continue; 
                                        $a = stat($fullpath); 
                                        $files[$fullpath]['size'] = (is_dir($fullpath)) ? 0 : $a['size']; 
                                        $files[$fullpath]['name'] = $file; 
                                        $files[$fullpath]['type'] = filetype($fullpath); 
                                        $files[$fullpath]['hash'] = (is_dir($fullpath)) ? "" : md5_file($fullpath); 
                                        $files[$fullpath]['mtime'] = $a['mtime']; 
                                        $files[$fullpath]['level'] = $level; 
                                        if (is_dir($fullpath)) { 
                                                getFiles($fullpath,$level+1); 
                                        } 
                                } 
                                closedir($dh); 
                        } 
                } 
                
                return $files; 
                
        } 
        
        function fileExtension($file) { 
                return substr($file,strrpos($file,".")+1); 
        } 

        function sortby_date_asc($ar1, $ar2) { 
                if ($ar1['mtime']<$ar2['mtime']) { return -1; } elseif ($ar1['mtime']>$ar2['mtime']) { return 1; } 
                return 0; 
        } 

        function sortby_date_desc($ar1, $ar2) { 
                if ($ar1['mtime']<$ar2['mtime']) { return 1; } elseif ($ar1['mtime']>$ar2['mtime']) { return -1; } 
                return 0; 
        } 

        function sortby_name_asc($ar1, $ar2) { 
                if ($ar1['name']<$ar2['name']) { return -1; } elseif ($ar1['name']>$ar2['name']) { return 1; } 
                return 0; 
        } 

        function sortby_name_desc($ar1, $ar2) { 
                if ($ar1['name']<$ar2['name']) { return 1; } elseif ($ar1['name']>$ar2['name']) { return -1; } 
                return 0; 
        } 

        function sortby_size_asc($ar1, $ar2) { 
                if ($ar1['size']<$ar2['size']) { return -1; } elseif ($ar1['size']>$ar2['size']) { return 1; } 
                return 0; 
        } 

        function sortby_size_desc($ar1, $ar2) { 
                if ($ar1['size']<$ar2['size']) { return 1; } elseif ($ar1['size']>$ar2['size']) { return -1; } 
                return 0; 
        }
?>
<?php
 $files = getFiles("../esmpd_minutes"); 
        
        
        echo "<br><br>"; 
        uasort($files, 'sortby_date_desc'); 
		
        foreach($files as $file => $data) { 
                echo "<li class='.listitem'><a href=\""  . $file . "\">" . $file . "</a></li><br />\n"; 
        } 
?>
The problem is that I am getting the path:

Code: Select all

../esmpd_minutes/03_27_07 Single Econ Launch Screen.wpd

../esmpd_minutes/03_23_07 Electronic Reporting.wpd

../esmpd_minutes/03_20_07 Web Applications Moving to Blade.wpd

../esmpd_minutes/02_21_07 Current Surveys Test Environment.wpd

../esmpd_minutes/02_27_07 Web Applications Moving to Blade.wpd
What do I change to only get the document name?

Thanks from a complete PHP-dunce.
Post Reply