Can someone please help me with this recursive function! It's messing up the incrementing of $x. I don't know what's wrong and I've been looking at it for so long now.

function list_dir($handle, $path) {
	// Loop over the directory and don\"t display certain files
	global $x;
	$x = 0;
	echo "<ul>";
	//running the while loop
	while (false !== ($file = readdir($handle))) {
		$extension = strtolower(substr(strrchr($file, '.'), 1)); 
		$dir =$path.'/'.$file;
		global $file_path;
		$file_path[$x] = $path;
		if(is_dir($dir) && $file != '.' && $file !='..' ) {
			$handle = opendir($dir) or die("unable to open file $file");
			echo "<li><b>$file</b></li>";
			list_dir($handle, $dir);
		}
		
		elseif($extension == "zip") {
			unlink($file);
		}
		
		elseif($extension == "mp3" || $extension == "mpa" && $file != '.' && $file !='..') {
			echo "<li><input type = \"checkbox\" name = \"file$x\" value = \"$file\" /><input type = \"hidden\" name = \"file".$x."_path\" value = 				\"".$file_path[$x]."\" /><a href=\"".$file_path[$x]."/$file\">$file</a></li>";
		}
		$x++;
	}

    echo "</ul>";
}

Recommended Answers

All 15 Replies

I don't think there is a need to use $x. In general it is not a good idea to use globals in recursive functions. I have no possibility to test my code, but you could try this:

function list_dir($handle, $path, $x = 0) {
	// Loop over the directory and don\"t display certain files
	echo "<ul>";
	//running the while loop
	while (false !== ($file = readdir($handle))) {
		$extension = strtolower(substr(strrchr($file, '.'), 1)); 
		$dir =$path.'/'.$file;
		if(is_dir($dir) && $file != '.' && $file !='..' ) {
			$handle = opendir($dir) or die("unable to open file $file");
			echo "<li><b>$file</b></li>";
			$x = list_dir($handle, $dir, $x);
		}
 
		elseif($extension == "zip") {
			unlink($file);
		}
 
		elseif($extension == "mp3" || $extension == "mpa" && $file != '.' && $file !='..') {
			echo "<li><input type = \"checkbox\" name = \"file$x\" value = \"$file\" /><input type = \"hidden\" name = \"file".$x."_path\" value = 				\"".$path."\" /><a href=\"".$path."/$file\">$file</a></li>";
		}
		$x++;
	}
    echo "</ul>";
  return $x;
}

I am not sure what the point of $x is in that function besides being a counter. But this should solve your recursion issue.

<?php 

//Path to starting point
$path = '/your/path/goes/here';

//Create a recursive directory iterator
$iterator = new RecursiveDirectoryIterator($path);

echo "<ul>\n";
$x=0;

//Foreach iteration do something.
foreach (new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::SELF_FIRST) as $file)
{
	
	$extension = strtolower(end(explode('.',$file->getBasename())));
	
	if( $file->isDir() )
	{
		echo "<li><b>{$file->getBasename()}</b></li>\n";

	}
	else if( $file->isFile() && $extension == 'zip' )
	{
		//unlink($file->getPathname());
	}
	else if( $file->isFile() && ($extension == 'mp3' || $extension == 'mpa') )
	{
		echo "<li>
		      <input type = \"checkbox\" name = \"file$x\" value = \"{$file->getBasename()}\" />
		      <input type = \"hidden\" name = \"file".$x."_path\" value = \"{$file->getPathname()}\" />
		      <a href=\"{$file->getPathname()}\">{$file->getBasename()}</a>
		      </li>\n";
	}
	++$x;
}
echo "</ul>";

It appears $x is just being used so there is a unique number to put into the checkboxes. However with php if you are using this to build a form that you can select music files to delete or move or whatever, using a checkbox name of `anything[]` will create a php array of checkbox values on submit.

Then your checkbox value can be the actual path to the file including the filename. No need to have the hidden input then.

Awesome! Thanks for the help. That wasn't the exact solution, but it helped tremendously and pointed out a fatal flaw in my code. Every time list_dir was called it would reset $x to 0. So I defined $x outside the function, and passed it in as a variable. My code for that portion now looks like this.

$x = 0;
function list_dir($handle, $path,$x) {
	// Loop over the directory and don\"t display certain files
	echo "<ul>";
	//running the while loop
	while (false !== ($file = readdir($handle))) {
		$extension = strtolower(substr(strrchr($file, '.'), 1)); 
		$dir =$path.'/'.$file;
		global $file_path;
		$file_path[$x] = $path;
		if(is_dir($dir) && $file != '.' && $file !='..' ) {
			$handle = opendir($dir) or die("unable to open file $file");
			echo "<li><b>$file</b></li>";
			list_dir($handle, $dir,$x);
		}
		
		elseif($extension == "zip") {
			unlink($file);
		}
		
		elseif($extension == "mp3" || $extension == "mpa" && $file != '.' && $file !='..') {
			echo "<li><input type = \"checkbox\" name = \"file$x\" value = \"$file\" /><input type = \"hidden\" name = \"file".$x."_path\" value = 				\"".$file_path[$x]."\" /><a href=\"".$file_path[$x]."/$file\">$file</a></li>";
		}
		$x++;
	}

    echo "</ul>";
    return $x;
}

I was writing my reply as you were adding your last reply. Thank you. I will try this simpler method out. I did not know it automatically saved them in an array.

I'm trying mschroeder's method, and it's coming up with this error for each list item.

Strict Standards: Only variables should be passed by reference in /opt/lampp/htdocs/Music/index.php on line 97

Also, it is no longer indenting the filenames as appropriate. For instance Dir, subdir indented from that, filenames indented from that.

post what is on line 97 of your file. There is nothing in my code that is passed by reference.

The indentation will be a little more tricky but i'll see what i can do.

This would be line 97

$extension = strtolower(end(explode('.',$file->getBasename())));

I suppressed the error for now. And thanks, I really appreciate the help.

If at all possible, could you help me remove . and .. from the list of files shown? Thought I knew how, but I couldn't figure it out.

change that line to:

$parts = explode('.',$file->getBasename());
$extension = strtolower(end($parts));

apparently explode returns its value by reference.

Are . and .. showing? In my quick testing they didn't show up at all.

Yeah they're showing up several times actually scattered throughout the files.

I've now tested it on both linux (centos) and windows (xp) and both php 5.2.10 and php 5.3.0 and don't see the dot directories showing up.

<?php 
error_reporting(E_ALL | E_STRICT);

$path = '/path/to/file';

$iterator = new RecursiveDirectoryIterator($path);
$recurse = new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::SELF_FIRST);
echo "<ul>\n";
$x=0;
foreach ( $recurse as $file)
{
	$parts = explode('.',$file->getBasename());
	$extension = strtolower(end($parts));
	
	if( $file->isDir() && !$recurse->isDot() )
	{
		echo "<li><b>{$file->getBasename()}</b></li>\n";
		
	}
	else if( $file->isFile() && $extension == 'zip' )
	{
		//unlink($file->getPathname());
	}
	else if( $file->isFile() && ($extension == 'mp3' || $extension == 'mpa') )
	{
		echo "<li>
		      <input type = \"checkbox\" name = \"file$x\" value = \"{$file->getBasename()}\" />
		      <input type = \"hidden\" name = \"file".$x."_path\" value = \"{$file->getPathname()}\" />
		      <a href=\"{$file->getPathname()}\">{$file->getBasename()}</a>
		      </li>\n";
	}
	++$x;
}
echo "</ul>";
Member Avatar for diafol
$op = "<select name='opts' id='opts'>";
$dir = new DirectoryIterator( '/www/test/' );
foreach($dir as $file ){
  if(!$file->isDot() && !$file->isDir() && preg_match("/.mp3$/",$file->getFilename())) {
    $op .= "<option value='{$file->getFilename()}'>{$file->getFilename()}</option>";
  }
}
$op .= "<select>";
echo $op;

The above should print out all mp3 files to a dropdown. If you want to include other extensions, just change the regex in the preg_match parameter. 9 lines - should be nice. Cannibalize to your needs (ul list, etc).

So that solved some of the dots. The problem comes in when I get to a 3rd/4th level directory, Music->Artist->Album->Disc1 for instance. Then the dots start showing up again.

OOPS! Forgot to change one small part to what mschroeder suggested. The dots are gone. Any ideas on the indentation?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.