tags:

views:

67

answers:

1

I'm using this code to process my folders and files with two subs:
"sub folders" for folder names only
"sub files" for file names with extensions only

But I realized that "sub folders" messes with my files with extensions during the rename process.

How to distinguish the processes from one another or what is the intelligent way to tell "sub folders" to rename "names" with no extension and "sub files" to rename "names" with externsion?

find(\&folders, $dir_source); 
sub folders {
    my $fh = $File::Find::dir;
    my $artist = (File::Spec->splitdir($fh))[3];        

    if (-d $fh) {
        my $folder_name = $_;

        # some substitution

        rename $folder_name, $_;
    }
}


find(\&files, $dir_source); 
sub files {
    /\.\w+$/ or return;
    my $fn = $File::Find::name;

    my ($genre, $artist, $boxset, $album, $disc);   
    if ($fn =~ /Singles/ or $fn =~ /Box Set/) {
         ($genre, $artist, $boxset, $album, $disc) = (File::Spec->splitdir($fn))[2..6];
     }
     else {
         ($genre, $artist, $album, $disc) = (File::Spec->splitdir($fn))[2..5];
     }

     if (-e $fn) {
         my $file_name = $_;

         # some substitution

         rename $file_name, $_;
     }  
 }
A: 

File::Find::find() calls your sub for every file and folder. If you only want to affect folders, then ignore files:

And you'll need to call finddepth() instead of find(), since you're changing directory names (you'll want to rename the "deeper" directories before the more "shallow" ones).

finddepth(sub {
  return unless -d;

  (my $new = $_) =~ s/this/that/ or return;
  rename $_, $new or warn "Err renaming $_ to $new in $File::Find::dir: $!";
}, ".");

Alternative for multiple substitutions:

finddepth(sub {
  return unless -d;

  my $new = $_;
  for ($new) {
    s/this/that/;
    s/something/something_else/;
  }
  return if $_ eq $new;

  rename $_, $new or warn "Err renaming $_ to $new in $File::Find::dir: $!";
}, ".");

And in the files sub, I'd make the first statement:

return unless -f;
runrig
Your suggestion is awesome without a doubt. I'm only having difficulties to pass several my $new; ($new = $_) =~ s/something/something else/ or return; because it only works when one.
thebourneid
Not sure what you mean. You want to do several s/// on the same variable and rename if any of them change the value?
runrig
Yes. In my complete code I have 10-15 s/// and if anyone of them is met in ANYWHERE in ANY folder - rename. But I guess when "or return" is added - it stops the processing if something is not met. Am I correct?
thebourneid
Ok, I've added an update.
runrig
Yes.Works like a charm now (((:Thanks.
thebourneid