http://www.perlmonks.org?node_id=809171

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

Monks: I need to check each of the below directories for any files. If there is a file, I need to move it to a temp directory. I would like to know if there is a more efficient way to check each directory. I'm thinking a loop of some sort, but there is a gap of numbers.
#!/usr/bin/perl -w use strict; use warnings; use File::Copy; if (-e "D:/DOWNLOAD/DISTRBTN/I01/B01/") { } if (-e "D:/DOWNLOAD/DISTRBTN/I01/B02/") { } if (-e "D:/DOWNLOAD/DISTRBTN/I01/B03/") { } if (-e "D:/DOWNLOAD/DISTRBTN/I01/B04/") { } if (-e "D:/DOWNLOAD/DISTRBTN/I01/B05/") { } if (-e "D:/DOWNLOAD/DISTRBTN/I01/B06/") { } if (-e "D:/DOWNLOAD/DISTRBTN/I01/B07/") { } if (-e "D:/DOWNLOAD/DISTRBTN/I01/B08/") { } if (-e "D:/DOWNLOAD/DISTRBTN/I01/B09/") { } if (-e "D:/DOWNLOAD/DISTRBTN/I01/B10/") { } if (-e "D:/DOWNLOAD/DISTRBTN/I01/B11/") { } if (-e "D:/DOWNLOAD/DISTRBTN/I01/B12/") { } if (-e "D:/DOWNLOAD/DISTRBTN/I01/B13/") { } if (-e "D:/DOWNLOAD/DISTRBTN/I01/B14/") { } if (-e "D:/DOWNLOAD/DISTRBTN/I01/B15/") { } if (-e "D:/DOWNLOAD/DISTRBTN/I01/B16/") { } if (-e "D:/DOWNLOAD/DISTRBTN/I01/B17/") { } if (-e "D:/DOWNLOAD/DISTRBTN/I01/B18/") { } if (-e "D:/DOWNLOAD/DISTRBTN/I01/B19/") { } if (-e "D:/DOWNLOAD/DISTRBTN/I01/B20/") { } if (-e "D:/DOWNLOAD/DISTRBTN/I01/B21/") { } if (-e "D:/DOWNLOAD/DISTRBTN/I01/B22/") { } if (-e "D:/DOWNLOAD/DISTRBTN/I01/B50/") { } if (-e "D:/DOWNLOAD/DISTRBTN/I01/B60/") { } if (-e "D:/DOWNLOAD/DISTRBTN/I01/B70/") { } if (-e "D:/DOWNLOAD/DISTRBTN/I01/B80/") { } if (-e "D:/DOWNLOAD/DISTRBTN/I01/B97/") { }

Replies are listed 'Best First'.
Re: Check Directories for Files
by almut (Canon) on Nov 24, 2009 at 19:40 UTC
    I'm thinking a loop of some sort, but there is a gap of numbers.

    You could still use a loop, e.g.

    for my $n (1..22,50,60,70,80,97) { my $path = sprintf "D:/DOWNLOAD/DISTRBTN/I01/B%02d/", $n; if (-e $path) { #... } }
Re: Check Directories for Files
by toolic (Bishop) on Nov 24, 2009 at 19:41 UTC
    This will find all files in the subdirectories of the Bxx dirs which you specified. This will not recurse below the Bxx dirs. File::Slurp
    use strict; use warnings; use File::Slurp qw(read_dir); my $path = 'D:/DOWNLOAD/DISTRBTN/I01/B'; my @dirs = map { sprintf "$path%02d/", $_ } 1..22, 50, 60, 70, 80, 97; for my $dir (@dirs) { my @files = grep { -f "$dir/$_" } read_dir($dir); # do something with files }
    If you really want all Bxx dirs, then @dirs could be simplified using glob.

    Update: added grep to just get files.

Re: Check Directories for Files
by halfcountplus (Hermit) on Nov 24, 2009 at 19:33 UTC
    Since these appear to be in a tree, you might want to investigate File::Find, which works recursively. You can use the callback to the find() to move the files found to wherever.
    find (\&checkfor, "D:/DOWNLOAD/DISTRBTN/I01/"); sub checkfor { if (-f $_) { print $File::Find::name."\n" }; }
    That will print out the full pathnames of all files in DISTRVTN/IO1 and all of it's subdirectories.
Re: Check Directories for Files
by Your Mother (Archbishop) on Nov 24, 2009 at 20:07 UTC

    Another approach. You should be able to see how you could recurse into sub-dirs with the same idea. Path::Class.

    use Path::Class (); my $dir = Path::Class::Dir->new("D:/DOWNLOAD/DISTRBTN/I01/"); for my $file ( grep { not $_->is_dir } $dir->children ) { print $file, $/; }
Re: Check Directories for Files
by baxy77bax (Deacon) on Nov 24, 2009 at 19:43 UTC
    hi,

    well Perl has got this two cool functions (among others:)) :

    opendir(); readdir(); so what you could do is: use strict; use warnings; use File::Copy; opendir (DIR,"./path") || die "$!"; # this opens the directory foreach my $i(readdir DIR){ next if (/\./g || grep{$_=~/$i/g}22..50); move("./path/$i", "/tmp/$i"); # if (-e "./path/$i"); } closedir DIR;
    that is it :)

    UPDATE:

    my bad, tollic is right, so basically what you do is check if the var in question is a regular file or not:

    next unless(-f "./path/$i" || !grep{$_=~/$i/g}22..50);
    sorry :)
      next if (/\./g);
      That will skip all files and sub-directories which contain a literal dot in the name, such as 'file.txt'. It will not skip any directories which do not have a dot, such as 'junk'.
Re: Check Directories for Files
by leocharre (Priest) on Nov 24, 2009 at 20:40 UTC
    Just use bash (I'm sorry, Richard! well, yes, bash or whatnot- but.. the real star here is;) Use gnu findutils
    for dir in $(find /rootdir/101/ -type d -name "B??"); do find $dir -type f -exec rm '{}' \; ; done; # or to move elsewhere # do find $dir -type f -exec mv '{}' /tmp/foundstuff/ \; ;
    If you know to expect the filesystem hierarchy you suggested- There's not even a need to play with the B?? dirs..
    $ find /rootdir/101/ -type f -exec mv '{}' /tmp/foundstuff/ \;
      Thank you all for your suggestions.