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 strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

how can I get a list of a directory's subdirectories? 2

Status
Not open for further replies.

greedyzebra

Technical User
Sep 5, 2001
140
US
Though it seems easy to get all of the files within a subdirectory, the name of the directory is important for what I want to do and I would like to get a list of subdirectories and then operate on them (and the files they each contain) individually. Any ideas?

Thanks.
 
@list = `find / -type d`



Blue [dragon]

If I wasn't Blue, I would just be a Dragon...
 
Here is a little longer solution but equally effective.

use File::Find;

find (\&wanted, "$RootDir");

foreach (@array) {
print "$_\n";
}

sub wanted {
-d and push(@array,$File::Find::name);
}
 
If you are after the contents of a directory, and the contents of the directories within it, and the contents within the directories within that etc... You are talking about recursion.

This script is more complicated than those above but will do exactly as I have described, basically displaying the entire directory tree starting off at the level you choose:

Beware, however, that if you specify a very high level directory (eg: "C:/" on windows or "/" on Unix) the script may take quite some time as it explores your entire file system.

This script features a subroutine which calls itself if a file it encounters is actually a directory.

In my example you should see a list of all file and directory paths starting from the $topDirectory you specify. Directories will be highlighted in blue if you are using a web browser to view the results:

#!/usr/bin/perl

print "Content-type:text/html\n\n";

# Set up the directory level you want to start at . = 'this directory'
$topDirectory=".";

getFiles($topDirectory);

sub getFiles{
my $useDirectory=$_[0];

opendir(DIR,$useDirectory);
my @files=readdir(DIR);
close(DIR);

# Must remove first two results (. and ..) or we will get stuck in an infinite loop
shift(@files);
shift(@files);

foreach my $file(@files){
# Output this file and path
my $showPath = $useDirectory."/".$file;
if (-d $useDirectory."/".$file){
# It is a directory so you can do any 'directory only' things here
$showPath=&quot;<span STYLE=\&quot;color:#0000ff\&quot;><b>$showPath</b></span>&quot;;
getFiles($useDirectory.&quot;/&quot;.$file);
}
print $showPath.&quot;<br>\n&quot;;
}
}


Hope that helps!
 
racklet's probably got the &quot;best&quot; solution, but if you only care about the first tier of subdirectories, here's a simple, short one:
Code:
my $parent = 'c:/winnt';
my @subdirs = grep -d, glob &quot;$parent/*&quot;;
It does use the shell (sometimes), but isn't OS specific, so it remains more portable than a system call. The list will be as fully-qualified as the $parent you give it. But it doesn't give you 2nd-tier subdirectories. For that you'd need a recursive call, like Tyger's, but if you're going that far, you should just use the File::Find module that does that so very well already.

----------------------------------------------------------------------------------
...but I'm just a C man trying to see the light
 
Amemdment,

I didn't see that you also want the file names.

You can change the code to this:

use File::Find;

find (\&wanted, &quot;$RootDir&quot;);

foreach (@array) {
print &quot;$_\n&quot;;
}

sub wanted {
-f and push(@array,$File::Find::name);
}

I will return the full path (directory and filename) to each file in ALL directories, sub-directories, sub-sub-directories, from the starting directory that you specify. If for whatever reason you want to have a separate list of directory and filenames, you could do something like this:

use File::Find;

find (\&wanted, &quot;$RootDir&quot;);

foreach (@array) {
print &quot;$_\n&quot;;
}

sub wanted {
-d and push(@DirArray,$File::Find::name);
-f and push(@FileArray,$File::Find::name);
}

Additionally, if you want to find files of just a certain extension (say .html), then you can do something like this:

use File::Find;

find (\&wanted, &quot;$RootDir&quot;);

foreach (@array) {
print &quot;$_\n&quot;;
}

sub wanted {
/\.html/ or return;
-f and push(@array,$File::Find::name);
}
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top