开发者

Zero pad rename e.g. Image (2).jpg -> Image (002).jpg

I need to rename al开发者_如何学JAVAl the images as the title explains in all sub-folders. I'm thinking of extracting with regex the number inside the parenthesis then renaming it. Searching around I saw there are tools like rename and mmv but I couldn't get them to pad-rename the jpgs.

I'll appreciate any advise to tackle my problem.

BTW: is for Windows and I have cygwin bash and perl.

Edit:

Conclusions after experimenting with all the answers.

  1. Cygwin rename is not good, the one I could get to work doesn't accept regex, but definitely a nice option, e.g. by running a Linux VM and mounting a Win SharedFolder.
  2. You can build a better rename tool for Cygwin with this shell script using sed.
  3. The Windows equivalent for pwd is simply cd.
  4. Hugmeir posted a promising solution using Perl 5.13+ which are dev releases, but by the time you may be reading this, probably that will be stable.
  5. The pad_left sub may not be a better alternative to printf syntax, but it works.


The rename command could do that:

rename 's/\d+/sprintf("%03d",$&)/e' *.jpg

With subdirectories:

find . -type f -name \*.jpg -print0|xargs -0 rename 's/\d+/sprintf("%03d",$&)/e'


The below code was tested on Linux; I don't know what you might have to modify to get it to work in your environment. Furthermore I haven't included any searching of sub-directories for .jpg files; if you'd like me to modify the code in that way, please let me know.

(EDIT: for a sub-directories-wide search, please see the program version further down)

use strict;
use warnings;

sub pad_left {
   my $num = shift;

   if ($num < 10) {
      $num = "00$num";
   }
   elsif ($num < 100) {
      $num = "0$num";
   }

   return $num;
}

my @files = glob "*.jpg";

my @padded_names = map {
                          my $name = $_;
                          $name =~ s/^([\w ]+\()(\d+)\)/$1 . &pad_left($2) .')'/e;
                          $name;
                       } @files;

foreach (0..$#files) {
   rename($files[$_], $padded_names[$_]);
   print "$files[$_] --> $padded_names[$_]\n";
}

The above program renames the files and prints the following:

file(1).jpg --> file(001).jpg
file(2).jpg --> file(002).jpg
file(20).jpg --> file(020).jpg
file(200).jpg --> file(200).jpg

HTH

EDIT: Here is an improved version of the above program - it now also incorporates searching of sub-directories for .jpg files. I know my code is no longer required as by now an answer addressing the sub-directory problem has been given, but hey... :)

use strict;
use warnings;
use File::Find;

sub pad_left {
   my $num = shift;

   if ($num < 10) {
      $num = "00$num";
   }
   elsif ($num < 100) {
      $num = "0$num";
   }

   return $num;
}

sub new_name {
   if (/\.jpg$/) {
      my $name = $File::Find::name;
      my $new_name;
      ($new_name = $name) =~ s/^(.+\/[\w ]+\()(\d+)\)/$1 . &pad_left($2) .')'/e;
      rename($name, $new_name);
      print "$name --> $new_name\n";
   }
}

chomp(my $localdir = `pwd`);# invoke the script in the parent-directory of the
                            # image-containing sub-directories

find(\&new_name, $localdir);


perl -MFile::Find::Rule -E 'rename($_, s/ \( \K ([0-9]+) (?= \) ) / sprintf("%03s", $1) /rex) for File::Find::Rule->file->name("*.jpg")->in($ARGV[0])' directory_here

This will only work with 5.13+ Perls though, due to the /r flag.

EDIT: For Windows, you'll have to change the outer quotes with double quotes, and either escape the ones in the sprintf and name, or use a different delimtier, ala qq!%03d!

EDIT2: Woah, totally screwed up my delimiters there.


Again on a tangential path, if you're on windows and you goal is to rename files rather than do some programming), try freeware Siren (http://www.scarabee-software.net/en/siren.html) It does exactly what is required, e.g. try the following expression Image \(%N1{3}\).%le. In particular, check out the %X* expressions catering specifically for images.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜