On Friday 09 April 2004 10:54, you wrote:
> Hi,
>
> I'm trying to create a perl program that will recurse into
>
> subdirectories. I have:
> > sub scandir {
> >     local $dirname=shift;
> >

You should use "my $dirname = shift;" instead of "local" here. It's safer.

> >     opendir DIR, $dirname or die "Couldn't open ${dirname}: $!\n";
> >

Just for safeness, it would be better if you localize DIR here:

<<<
local (*DIR);
opendir DIR...
>>>

> >     local $direntry;

Again -  my $direntry;

> >     while( $direntry=readdir(DIR) ) {

Instead of using readdir in a loop, I strongly recommend that you read all the 
entries into an array and then loop on it:

my @entries = readdir(DIR);
closedir(DIR);
foreach $direntry (@entries)
{
..
}

Otherwise, many dirhandles will be opened, and I'm not sure if the results 
will be very expectful. (with local and all)

> >         if( $direntry!~/^\./ ) {

Do you want to avoid only "." and ".." or any directory that starts with "."? 
Your code does the latter.

> >             local @state=stat($dirname.$direntry);
> >             print "$dirname$direntry $state[2]\n";
> >             if( (($state[2] & ~7777)>>12) ==4 ) { # A directory - recurse

This can be simplified into: 

<<<
if (-d $dirname.$direntry). { # A directory - recurse
>>>
"-d" is a file check that checks if a file is a directory. Check "perldoc -f 
-X" for more information.  

> >                 scandir($dirname.$direntry."/");

This is good. Albeit many people like to use interpolation:

scandir("$dirname$direntry/");

> >             }
> >         }
> >     }
> >
> >     closedir DIR;
> > }
>
> 1. I know, I write perl like a C programmer, I can't help it. Feel free
> to show me how it's done.

:-)

> 2. For some strange reason, the moment I recurse once, the entire loop
> structure exits. I suspect it's because the DIR handle is global. Will
> any perl guru comment on how it's supposed to be done?

If you "local"ize *DIR, it won't happen.

> 3. What the @$([EMAIL PROTECTED] is the difference between "my" and "local"? Which
> one should I use here?
>

"my" declares a lexically-scoped variable. It is similar to (define) in 
Scheme. The value of this variable is not propagated to subsequent function 
calls (unless they are closures). So for example:

<<<
#!/usr/bin/perl -w

use strict;

my $myvar = 3;

sub my_called_function
{
    print "In called: \$myvar = $myvar\n";

    $myvar = 10;
}

sub my_caller_function
{
    my $myvar;

    $myvar = 500;

    my_called_function();

    print "In caller: \$myvar = $myvar\n";
}

my_caller_function();

print "In Global: \$myvar = $myvar\n";
>>>

will print:

<<<
In called: $myvar = 3
In caller: $myvar = 500
In Global: $myvar = 10
>>>

"local" creates a dynmically scoped localization. The value of the variable is 
recorded when the local is encountered, and restored once the block exits. It 
is propogated to all subsequent function calls. So for example:

<<<
#!/usr/bin/perl -w

$myvar = 3;

sub my_called_function
{
    print "In called: \$myvar = $myvar\n";

    $myvar = 10;
}

sub my_caller_function
{
    local $myvar;

    $myvar = 500;

    my_called_function();

    print "In caller: \$myvar = $myvar\n";
}

my_caller_function();

print "In Global: \$myvar = $myvar\n";
>>>

prints:

<<<
In called: $myvar = 500
In caller: $myvar = 10
In Global: $myvar = 3
>>>

Generally, "my" should be used for all regular variables (scalars, arrays and 
hashes) because it's safer, while "local" should be used for filehandles, and 
built-in variables. (the ones in "perldoc perlvar") This is because they 
cannot be effectively scoped with my.

Hope it helps. There's more information about it on the Web and in the Perl 
documentation.

As others noted, you can use the "File::Find" Perl module to traverse a 
directory tree.

Regards,

        Shlomi Fish

-- 

---------------------------------------------------------------------
Shlomi Fish      [EMAIL PROTECTED]
Homepage:        http://shlomif.il.eu.org/

Quidquid latine dictum sit, altum viditur.
        [Whatever is said in Latin sounds profound.]

=================================================================
To unsubscribe, send mail to [EMAIL PROTECTED] with
the word "unsubscribe" in the message body, e.g., run the command
echo unsubscribe | mail [EMAIL PROTECTED]

Reply via email to