Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks!
I am working on this script to list all .pl and .pm files in a directory and later in all found directories. The code I have works until a given directory given list all files, but I am stuck getting to the file level to look for the Perl modules been used by each file found. I have the sub routine that will do that just having problem in make this code work with what I already have. Here is the code:
#!/usr/bin/perl -w use strict; use CGI qw(:header); use CGI::Carp qw(fatalsToBrowser); use CGI qw/:standard/; my $q = new CGI; my $show = param("show"); #my $input_dir = $ARGV[0] || '.' ; my $input_dir = "../my_directory"; my $arg_name = $q->param( 'arg_name' ) || ''; #arg must be "files" my $file_name = $q->param( 'fname' ) || ''; #arg must be a file name +found in the directory above print header(); print "<html> <head><title>Directory Tree 4</title> <script type=\"text/javascript\" src=\"../../aqtree3.js\"></script> <script type=\"text/javascript\" src=\"../../aqtree3clickable.js\"></s +cript> <link rel=\"stylesheet\" href=\"../../aqtree3.css\"> <link rel=\"stylesheet\" href=\"../../aqtree3clickable.css\"> </head> <body> Starting Directory<br> "; MAIN: { my @tree; dirwalk ($input_dir,\@tree); #print "L32-<OL>\n"; printtree(\@tree); #print "</OL>\n"; } sub dirwalk { my ($dir,$tree) = @_ ; push @{$tree},($dir =~ m#([^/]+$)#); opendir DIR, $dir || die "Couldnt open $dir - $!\n"; my @entries = grep !/^\.{1,2}$/, readdir(DIR); closedir (DIR); foreach my $item (@entries) { my $fullpath = "$dir/$item"; if ( -d $fullpath ) { dirwalk ( $fullpath,\@{$tree->[@{$tree}]}); } else { push @{$tree},$item; } } } sub printtree { my $tree = shift; my $c=-1; print "<ul class=\"aqtree3clickable\"><li><a href=\"#\">&nbsp;",shif +t @{$tree},"</a><br>\n"; foreach my $item ( @{$tree} ) { #print "<b>$item</b>"; $c++; if (ref $item eq "ARRAY" ) { printtree($item); } else { print "<ul><li><a href=\"tree.pl?arg_name=files&fname=$item\" +>\n"; print $item,"</a></li></ul>\n"; if($arg_name eq "files") { # I am trying to insert code to ca +ll get_modules to find all the modules used in each Perl script here get_modules($file_name); #print "here"; } } } print "</li>"; print "</ul>"; } sub get_modules { my ($file) = @_ ; my (@all_files, @all_mod); my $dir = "../../my_directory"; #this is the same as in $input_dir ab +ove opendir(DIR, $dir) or die $!; while (my $file = readdir(DIR)) { # just files next unless (-f "$dir/$file"); # Use a regular expression to find files ending in .pl and .pm in t +he directory next unless ($file =~ m/(\.pl|\.pm)$/); print "$file\n"; push @all_files, $file; } closedir(DIR); if( ($arg_name eq "files") && ( $file_name ) ) { print "<br>Perl Modules used by $file_name:<br>\n\n"; foreach my $files(@all_files) { open (FILE, "$dir/$files"); while(my $line= <FILE> ){ if(grep /\buse\b/, $line) { if( ($files eq "$file_name") && ($line!~/^#/g) ) { $line=~s/\buse\b//g; print "$line"; } } } close FILE; } } } print "<br>End </body> </html> ";

Thanks for the Help!

Replies are listed 'Best First'.
Re: Directory Tree Help!
by aquarium (Curate) on Oct 21, 2010 at 01:57 UTC
    and what's the nature of the problem? i.e. what doesn't the program do correctly that you would like help with.
    i did notice that you're looking for "use" surrounded by word boundary. not sure if you get a word boundary at the start of a line or not. in any case, you should be able to divide and conquer, by separating the grepping code into a little test script, and manually run it against example .pl files to watch output. if that works correctly, then the routine to generate filenames in the directory walk may need attention.
    the hardest line to type correctly is: stty erase ^H
      It runs ok, but once the directory tree expands and all the files listed there are displaying, these files needed to call the sub (by clicking) to get the modules that these files are using, and this is the part that doesn't work, I hope I made clear this time, thanks!

        Tip: "Doesn't work" doesn't work.

        We already know that it isn't doing what you wanted it to do (since you're having trouble or you wouldn't be here) so that phrase is useless.

        Instead, say what it actually did (copy and paste the result into code tags rather than typing it tho). Pointing out where things stopped matching what you expect is good too. Including the test results you expected is better.

        My personal preference for this problem would be to match
        /^\s*use\s+/
        or something along those lines. i'd use word boundary regexes when you need to tokenize whole lines of text into word units or similar. Have you tried at least to use your original regex without the initial word boundary, as per my earlier suggestion?
        if still not working..it's just a matter of running a single line of code with the regex, directly against any example .pl files you want to try. try and try again, adjusting the regex, until you get results you want. then put this regex in your script. sorry but i don't have regular access to perl as i type, at the moment.
        the hardest line to type correctly is: stty erase ^H