Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Reading directories and subdirectories using recursion

Status
Not open for further replies.

ahammad

Programmer
Sep 24, 2007
10
0
0
FR
Hello all,

I have a directory structure with lots of text files in it. I want to have a script that basically takes in the top level directory as a parameter, and it will read through all the directories and subdirectories and retrieve all the filenames.

I thought that the best way to tackle this is to use a recursive function to do the work of stepping through the directory structure. I'm not sure if there is a built in function that can do this sort of thing.

Here is what I have done so far:

Code:
sub checkForDir
{
	#grab directory as an input
	$directory = shift;
	
	#open the directory, and get all the content except ., .., and .svn (in case this is based on an svn checkout)
	opendir( DIR, $directory ); 
	@contents = grep !/(^\.\.?$)|(^\.svn$)/, readdir DIR;
	closedir( DIR );
		
	#now that we have the contents of the directory in @contents
	foreach( @contents )
	{
		print( $directory . '\\' . $_ . "\n");
		
		#attempt to check if the content is a directory or a file by trying to open it
		if( opendir( SubDir, $directory . '\\' . $_ ) )
		{
			#if we can open it, it's a directory			
			#push the directory into an array for later usage;
			push( @directories, $directory . '\\' . $_ );
			closedir( SubDir );
			
			#try to do recursion
			checkForDir( $directory . '\\' . $_ ); 
		}
			#otherwise, opendir will fail, which means it is most likely a file or something went horribly wrong
	}
	
	foreach( @directories )
	{
		print( $_ . "\n" );
	}

}

As of now, this sort of works. What it does is it reads the root directory, and then it will do recursion only for the first directory it finds, and it will ignore the rest. For example, say we have the following:

C:\ (this is passed as a parameter)
C:\abc
C:\Program Files
C:\ZXY

The script will be able to read those 3 directories, but it will only do the recursion on C:\abc and skip the other two. Within the recursive call of C:\abc, it will do the same thing (take first entry and skip the rest).

Can someone help me in finding the error? I tried to comment it as much as possible but I'm not sure if I was descriptive enough.

Cheers.
 
The use of global variables is probably the primary problem.

i.e. the "$directory = shift" -- without using "my" there, that $directory is the very same $directory as the one declared the first time. So when you recursively call the subroutine, all the variables get messed up from the first time the sub was called and are overwritten on the next call. So i.e. when it recurses into 'abc', @contents is replaced with what's inside 'abc', and no longer contains the other folders in C:\. When a folder in 'abc' goes through the sub, @contents is replaced again with what's inside that other folder.

If you declare all your variables with "my", it will keep them scoped inside the sub and when the sub is called recursively, it keeps all your variables separate.

Cuvou.com | My personal homepage
Code:
perl -e '$|=$i=1;print" oo\n<|>\n_|_";x:sleep$|;print"\b",$i++%2?"/":"_";goto x;'
 
i.e. the "$directory = shift" -- without using "my" there, that $directory is the very same $directory as the one declared the first time.

He should be using strict and declaring the variables but in this case each time the function is called he is passing in a new argument:

checkForDir( $directory . '\\' . $_ );

so $directory will have that new value. Assumes $_ has some value too.

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
Kevin, the problem is with the array [tt]@contents[/tt], that's rewritten at every new call, so only the first directory branch is explored.
Of course it is a must that all recursive subs will use only private variables, and that's additional to the rule that every program should [tt]use strict;[/tt] (rule that I follow rarely [blush]).
And ahammad, there's a simpler and more correct way of testing for a directory: the [tt]-d$dir[/tt] file switch.

Franco
: Online engineering calculations
: Magnetic brakes for fun rides
: Air bearing pads
 
His code works for me as-is. I tested it with a directory that is three levels deep and they were all opened and the file displayed (the display is not well formatted but thats another issue). So I don't know why it does not work for him. Could be a permissions problem.

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top