File::Glob - can it recurse?

R

Randall Perry

I'm guessing not from reading the docs.

Here's what I can do with 2 lines using system:
system("chown -R $user.$http_group www/*");
($? eq 0) || die "Couldn't chown $user.$group www/*\n";

I'd like to use the perl chown() command so I tried this:
@filenames = glob "/admin/new_account_page/*";
chown $uid, $gid, @filenames || die;

But it doesn't recurse through subdirectories. Is there a better way
to accomplish this than by using system()?

Randy
 
P

Paul Lalli

I'm guessing not from reading the docs.

Here's what I can do with 2 lines using system:
system("chown -R $user.$http_group www/*");
($? eq 0) || die "Couldn't chown $user.$group www/*\n";

I'd like to use the perl chown() command so I tried this:
@filenames = glob "/admin/new_account_page/*";
chown $uid, $gid, @filenames || die;

But it doesn't recurse through subdirectories. Is there a better way
to accomplish this than by using system()?


I feel like I'm taking on the job of advocating this module lately.

The standard File::Find module is helpful for recursing through
directories. The non-standard File::Find::Rule and File::Finder provide
alternate syntaxes as well.

(untested)

#!/usr/bin/perl
use strict;
use warnings;
use File::Find

my ($uid, $gid) = @ARGV; #assuming UID and GID are passed in command line.
my @files;

sub wanted{
push @files, $File::Find::name if -f $File::Find::name;
}

find (\&wanted, '/admin/new_account_page/');
chown $uid, $gid, @files or die "Cannot chown: $!";

__END__
 
B

Brian McCauley

Randall Perry wrote:

[ of glob() ]
But it doesn't recurse through subdirectories. Is there a better way
to accomplish this than by using system()?

File::Find
 
B

Ben Morrow

Quoth (e-mail address removed) (Randall Perry):
I'm guessing not from reading the docs.

Here's what I can do with 2 lines using system:
system("chown -R $user.$http_group www/*");
($? eq 0) || die "Couldn't chown $user.$group www/*\n";

I'd like to use the perl chown() command so I tried this:
@filenames = glob "/admin/new_account_page/*";
chown $uid, $gid, @filenames || die;

But it doesn't recurse through subdirectories. Is there a better way
to accomplish this than by using system()?

File::Find, as usual...

Ben
 
R

Randall Perry

But it doesn't recurse through subdirectories. Is there a better wayThanks for the input, but for me, the answer here is no. :)
Calling system() is much simpler.

Adding recursive capabilities to chown(), chmod() would be ideal.
 
U

Uri Guttman

RP> Thanks for the input, but for me, the answer here is no. :)
RP> Calling system() is much simpler.

RP> Adding recursive capabilities to chown(), chmod() would be ideal.

no that wouldn't be ideal. perl tries to keep its system calls as
similar as possible to the real kernel calls. chmod the system call
doesn't recurse but chmod the utility can. they are different things
even if they have the same name and have overlapping functionality. it
isn't hard to use file::find and then call chmod on the results (in the
callback or on the collected results.

the best thing to do would be to write a module that does this and put
it on cpan. then it will be easy to use and everyone can enjoy the
fruits of your labor. there is a file::chmod module which handles
different modes for setting the chmod bits but it doesn't recurse. maybe
you can work with its author to add recursion to it. forking out to a
process just to recurse is not my idea of a good thing.

uri
 
J

J. Romano

I'd like to use the perl chown() command so I tried this:

@filenames = glob "/admin/new_account_page/*";
chown $uid, $gid, @filenames || die;

But it doesn't recurse through subdirectories. Is there a better way
to accomplish this than by using system()?

There is a simple work-around to your problem, but it's not really
all that elegant.

One of the nice things about the glob() function is that it can
take wildcards in the directory names, as well as in the file names.
So you can replace your line:

@filenames = glob "/admin/new_account_page/*";

with:

@filenames = glob "/admin/new_account_page/*";
push @filenames, glob "/admin/new_account_page/*/*";
push @filenames, glob "/admin/new_account_page/*/*/*";

push @filenames, glob "/admin/new_account_page/*/*/*/*";
push @filenames, glob "/admin/new_account_page/*/*/*/*/*";
push @filenames, glob "/admin/new_account_page/*/*/*/*/*/*";

and now you have recursion that's five levels deep.

Like I said, this isn't really all that elegant of a solution,
since your directory structure may have more (or less) than five
levels of recursion. If it had twenty levels of nested directories,
you'd have to have 21 total glob() lines to get all your files! If it
had only two levels of recursion, then three of those lines would be
useless.

There is a work-around for this problem, too. You can always put
the glob string in a loop that stops when it finds no more files, like
this:

$globString = "/admin/new_account_page/*";
while ( @globbedFiles = glob($globString) ) # note the single "="
{
push @filenames, @globbedFiles;
$globString .= "/*"; # for the next time through the loop
}
print "Found files: @filenames\n";

This approach should work, but I have to say that the standard
approach is to use the File::Find module, as it was meant to be used
for tasks just like yours. If you find the documentation for
File::Find to be a bit confusing, you can use the "find2perl"
executable (which you probably already have) to create most of the
code for you, with this command:

find2perl /admin/new_account_page -name "*"

Then all you'd have to do is put this line of yours in the wanted()
subroutine:

chown $uid, $gid, @filenames or die;

and then run that script.

I hope this helps, Randy.

-- Jean-Luc
 
R

Randall Perry

Uri Guttman said:
chmod the system call
doesn't recurse but chmod the utility can. they are different things
even if they have the same name and have overlapping functionality.

Didn't know that.

Thanks everyone for the info.
 
R

Randall Perry

Uri Guttman said:
chmod the system call
doesn't recurse but chmod the utility can. they are different things
even if they have the same name and have overlapping functionality.

Didn't know that.

Thanks everyone for the info.
 
R

Randall Perry

Uri Guttman said:
chmod the system call
doesn't recurse but chmod the utility can. they are different things
even if they have the same name and have overlapping functionality.

Didn't know that.

Thanks everyone for the info.
 
R

Randall Perry

Uri Guttman said:
chmod the system call
doesn't recurse but chmod the utility can. they are different things
even if they have the same name and have overlapping functionality.

Didn't know that.

Thanks everyone for the info.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top