2010-12-30 5 views
2

Je dois renommer toutes les images comme l'explique le titre dans tous les sous-dossiers. Je pense à extraire avec regex le nombre à l'intérieur de la parenthèse, puis le renommer. En cherchant autour j'ai vu il y a des outils comme rename et mmv mais je ne pourrais pas les obtenir au pad-renommer les jpgs.Renommer le pad zéro par ex. Image (2) .jpg -> Image (002) .jpg

J'apprécierai n'importe quels conseils pour aborder mon problème.

BTW: est pour Windows et j'ai cygwin bash et perl.

Editer:
Conclusions après avoir expérimenté avec toutes les réponses.

  1. Cygwin rename est pas bon, celui que je pouvais aller au travail n'accepte pas regex, mais certainement une option intéressante, par exemple en exécutant une VM Linux et en montant un Win SharedFolder.
  2. Vous pouvez créer un meilleur outil rename pour Cygwin avec this shell script en utilisant sed. L'équivalent Windows pour pwd est simplement cd.
  3. Hugmeir a publié une solution prometteuse en utilisant Perl 5.13+ qui sont des versions de dev, mais au moment où vous lisez peut-être cela, ce sera probablement stable.
  4. Le sous-pad_left ne peut pas être une meilleure alternative à la syntaxe printf, mais cela fonctionne.

Répondre

1

Le code ci-dessous a été testé sous Linux; Je ne sais pas ce que vous pourriez avoir à modifier pour le faire fonctionner dans votre environnement. De plus, je n'ai inclus aucune recherche de sous-répertoires pour les fichiers .jpg; Si vous souhaitez que je modifie le code de cette façon, s'il vous plaît faites le moi savoir.

(EDIT: pour une recherche sous-répertoires à l'échelle, s'il vous plaît voir la version du programme plus bas)

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"; 
} 

Le programme ci-dessus renomme les fichiers et imprime les éléments suivants:

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: Voici une version améliorée de l'abov e programme - il incorpore maintenant la recherche de sous-répertoires pour les fichiers .jpg. Je sais que mon code est plus nécessaire que maintenant une réponse face au problème sous-répertoire a été donné, mais bon ... :)

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); 
+0

wow c'était rapide! Merci beaucoup. Si cela ne vous dérange pas, oui s'il vous plaît, aidez-moi aussi avec les sous-directeurs. –

+0

@Eric Fortis Ok, je vais essayer :) Attendez quelques minutes. – canavanin

+0

@Eric Fortis J'ai joué un peu plus longtemps que prévu, en fait> _ canavanin

7

La commande rename pourrait faire:

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

avec sous-répertoires:

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

merci pour le conseiller M. István –

+0

en fait c'est M. Karaszi, mais peu importe;) –

+0

On dirait que plus aucun effort n'est requis de mon côté alors :) – canavanin

1
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 

Cela ne fonctionne qu'avec 5.13+ Perls si, en raison du drapeau/r .

EDIT: Pour Windows, vous devrez changer les guillemets externes avec des guillemets doubles, et soit échapper ceux du sprintf et du nom, soit utiliser un délimiteur différent, ala qq!% 03d!

EDIT2: Woah, totalement foiré mes délimiteurs là.

+0

merci je vais aussi jouer avec ça aussi. –

+0

Une version rétrocompatible: perl -MFile :: Find :: Rule -E "pour (File :: Find :: Rule-> file-> nom (q! *. Txt!) -> in ('C:/My Dropbox ')) {(mon $ newname = $ _) = ~ s/\ (\ K ([0-9] +) (? = \))/Sprintf (qq!% 03s !, $ 1)/ex; rename $ _, $ newname} " – Hugmeir

+1

Voici un lien vers le blog de brian d foy sur le nouveau/r drapeau http://www.effectiveperlprogramming.com/blog/659 –

0

Encore une fois sur un chemin tangentiel, si vous êtes sur Windows et que votre but est de renommer les fichiers plutôt que de faire de la programmation), essayez freeware Siren (http://www.scarabee-software.net/en/siren. html) Il fait exactement ce qui est requis, par exemple essayez l'expression suivante Image \(%N1{3}\).%le. En particulier, consultez les expressions %X* traiteur spécifiquement pour les images.

Questions connexes