tags:

views:

540

answers:

5

I have a folder called Client which contains many subfolders. I want to create a Perl script to look at each of those subfolders and check for a folder there. If it is there, I want to skip it and move on, if it is not there, I want to create it and do some processing.

How do I go about looping through all of the subfolders and checking for the directory I want? I have found a lot of information on how to get all the files in a folder and/or subfolders, but nothing on checking for a directory within each subfolder.

A: 

Use File::Finder

Nifle
Why would you use File::Finder? I don't see how it makes this problem any easier.
brian d foy
+2  A: 
#!/usr/bin/perl

use strict;

use Fcntl qw( :DEFAULT :flock :seek );
use File::Spec;
use IO::Handle;

my $startdir = shift @ARGV || '.';
die "$startdir is not a directory\n"
    unless -d $startdir;
my $verify_dir_name = 'MyDir';

my $dh = new IO::Handle;
opendir $dh, $startdir or
    die "Cannot open $startdir: $!\n";
while(defined(my $cont = readdir($dh))) {
    next
        if $cont eq '.' || $cont eq '..';
    my $fullpath = File::Spec->catfile($dir, $cont);
    next
        unless -d $fullpath && -r $fullpath && -w $fullpath;
    my $verify_path = File::Spec->catfile($fullpath, $verify_dir_name);
    next
        if -d $verify_path;
    mkdir($verify_path, 0755);
    # do whatever other operations you want to $verify_path
}
closedir($dh);
chaos
Someone forgot a `use IO::Handle;`
Chris Lutz
Indeed. Better now. :)
chaos
A: 

The short answer is use File::FInd.

The long answer is first write a subroutine that validates the existence of the folder and if the folder is not there, create it and then do the processing needed. Then invoke the find method of the File::Find module with a reference to the subroutine and the starting folder to process all the subfolders.

David Harris
That's a lot of work for such a simple task. :)
brian d foy
+4  A: 

It's pretty easy once you break it into steps. Get a list of the subdirectories with glob then see which ones don't have the second-level directory. If you are using a File::Find-like module, you are probably doing too much work:

#!perl

use strict;
use warnings;

use File::Spec::Functions;

my $start  = 'Clients';
my $subdir = 'already_there';

# @queue is the list of directories you need to process
my @queue  = grep { ! -d catfile( $_, $subdir ) }   # filter for the second level
             grep { -d }                            # filter for directories
             glob catfile( $start, '*' );           # everything below $start
brian d foy
+8  A: 

Augh! Too much complexity in the above answers. The original question doesn't appear to be asking for a recursive traversal. As far as I can see, this is a perfectly sensible solution, and vastly more readable to boot:

foreach my $dir (glob "Client/*") {
    next if ! -d $dir;              # skip if it's not a directory
    next if -d "$dir/subfolder";    # skip if subfolder already exists
    mkdir "$dir/subfolder" or die;  # create it
    do_some_processing();           # do some processing
}

Seriously folks: opendir/readdir? Really?

Andy Ross
People get the module virus and they forget how to program. At least I'm not the only one who sees this. :)
brian d foy
Amen! +1 for KISS solution :)
DVK
Although, I'm tempted to downvote for not using "$!" in the error message from mkdir :)
DVK
Thank you! This works beautifully :-)