Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid

Filename fixer

by spm (Acolyte)
on Jul 18, 2001 at 14:09 UTC ( [id://97598] : CUFP . print w/replies, xml ) Need Help??

Fixes most of the most stupid filenames that you get while downloading a lot... I use this to create harmony from chaos in my Mp3 collection.
foreach (sort(<*>)) { $a = $_; s/ /_/g; s/(%20)/_/ig; s/(%25)//ig; $_ = lc($_); rename("$a", $_); }

Replies are listed 'Best First'.
Re: Filename fixer
by grinder (Bishop) on Jul 18, 2001 at 14:42 UTC
    1:foreach (sort(<*>)) { 2: $a = $_; 3: s/ /_/g; 4: s/(%20)/_/ig; 5: s/(%25)//ig; 6: $_ = lc($_); 7: rename("$a", $_); 8:}

    There are a number of comments that can be made about the code on each line.

    1. Sorting the results is a needless expense that you can do away with.
    2. Using $a (a package variable) should be shunned. You should use a lexical (declared with my). You should also choose a name that documents what it contains.
    3. s/ /_/g is better expressed as a single character transliteration with tr/ /_/, but...
    4. Since the following line also maps something to _, you should fold the two together into one regexp. Also, since nothing is done with the matched text you can drop the parentheses, and since none of the characters are case-sensitive, you can also drop the /i modifier.
    5. In a similar vein, you can drop the parentheses and the /i modifier.
    6. Were the above regular expressions in fact case-sensitive, you could put this line before them, to get it executed first, then in any event you wouldn't have to worry about case-sensitivity in the first place.
    7. There is no need to double quote a single scalar, that's just unnecessary interpolation. The compiler optimises this away, but it's a good habit to learn. Also, you're not checking the error return, so if something goes wrong (renaming to a file that exists), you'll never be informed.

    Wrapping all those comments up, we get something like this:

    foreach my $old( <*> ) { (my $new = lc $old) =~ s/ |%20/_/g; $new =~ s/%25//g; rename( $old, $new ) or warn "can't rename $old to $new: $!\n"; }

    For more information, you might want to visit this node, which talks about the same subject.

    update: oops! reading petral's reply made me realise I made a spelling mistake. Argh.

    Hope this helps!

    g r i n d e r
      1. Sorting the results is a needless expense that you can do away with.

      True.  But I often do it anyway, so I can follow the progress of the routine.  For instance, in this case you could ls the dir where it was operating every now and then.  Other times you might want to step through the debugger.  -- Not essential, but no harm and it can be useful (and all the io will swamp any extra time it takes).


      True, the new code is a lot better. I just threw it here because I had it, a little hack for my friend, and thought someone else might need it... However, I happen to like the $_ variable quite a lot, and try using it as much as possible. Therefore I would rather do:
      foreach (<*>) { (my $new = lc) =~ s/ |%20/_/g; $new =~ s/%25//g; rename($_, $new) or warn "can't rename $_ to $new: $!\n"; }
      Another thing is that I don't really like using the foreach $variable (@array) {} syntax... I rather use map $variable { } @array if I can't use the $_ variable.. But thanks anyway! spm.
Re: Filename fixer
by bikeNomad (Priest) on Jul 18, 2001 at 17:00 UTC
    Why would you want to trash the case of your filenames by always converting to lower case? Seems that you're losing something there if they already have meaningful case. And (assuming you're using an OS where case matters) you could clobber an existing file by doing this if the filenames differed only in the character case.

    (I guess if you're using Windoze, though, you haven't yet gotten used to using upper and lower case in your filenames)