Création automatique de dossier

Création automatique de dossier - Shell/Batch - Programmation

Marsh Posté le 23-08-2015 à 09:41:40    

Bonjour, je cherche un script ou un logiciel qui me permettrait lorsque je l’exécuterai dans un dossier de créer des dossiers portant comme nom la date de création des fichiers (2015.08.23 par exemple) contenus dans le dossier et déplaçant chaque fichier inclus dans chaque dossier correspondant à la date de création.
 
Je précise que je ne comprend rien en programmation.
 
Merci

Reply

Marsh Posté le 23-08-2015 à 09:41:40   

Reply

Marsh Posté le 23-08-2015 à 14:29:23    

Sous quel OS? Je suppose Windows car apparemment sous Linux il n'y a pas de date de création sauvegardée pour les fichiers...

 

Voici un truc en Perl bricolé à la va vite, absolument sans garantie, mais qui fonctionne bien chez moi sous XP (oui oui, très vieux  :o ). Faire valider par un pro et/ou tester intensément avant de l'utiliser en prod!

 

bug connu: ne gère pas les raccourcis, je suppose qu'il y en a pas...

 

Pour utiliser installer StrawberryPerl (ou ActiveStatePerl mais j'ai pas testé), sauvegarder le script sous script.pl dans le dossier où il y a les fichiers à traiter puis lancer perl script.pl en ligne de commande (ou créer un raccourci).

 

Si il y a beaucoup de fichiers on peut virer l'affichage, soit les deux print.

 
Code :
  1. use strict;
  2. use warnings FATAL => 'all';
  3. use autodie;
  4. use File::Copy; #copy() et move()
  5.  
  6. #!SANS GARANTIE!
  7.  
  8. #http://perldoc.perl.org/perlport.html
  9. #stat: [...] ctime is creation time instead of inode change time (Win32).
  10.  
  11. opendir DH, '.';
  12.  
  13. my $file;
  14.  
  15. while(($file=readdir DH))
  16. {
  17.    next if($file eq 'script.pl'); #à ajuster si changement de nom, faut pas que le script essaye de se déplacer lui-même...
  18.    next if(!-f $file); #si c'est un dossier on l'ignore
  19.    
  20.    print "file \"$file\" --> ";
  21.    
  22.    my @t=localtime((stat($file))[10]); #sortir la date de création au format UNIX et convertir
  23.  
  24.    my $age=sprintf("%04d.%02d.%02d", $t[5]+1900, $t[4]+1, $t[3]); #et mettre dans le bon format
  25.  
  26.    print "$age\n";
  27.    
  28.    if(!-e $age)
  29.    {
  30.        mkdir $age;
  31.    }
  32.    elsif(!-d $age)
  33.    {
  34.        die "erreur: le nom \"$age\" est déjà utilisé par un fichier!";
  35.    }
  36.    
  37.    if(-f $age.'\\'.$file)
  38.    {
  39.        die "erreur: collision: \"$file\" existe déjà dans dossier $age";
  40.    }
  41.    
  42.    copy($file, $age.'\\'.$file); #copy() pour copier ou move() pour déplacer
  43. }
  44.  


Message édité par rat de combat le 23-08-2015 à 14:32:37
Reply

Marsh Posté le 23-08-2015 à 17:25:45    

Merci énormément, le programme fonctionne parfaitement.


Message édité par maaon le 23-08-2015 à 17:35:54
Reply

Marsh Posté le 23-08-2015 à 17:51:22    

Par contre, comment faire si je veux que le script traite également les sous répertoires ?

Reply

Marsh Posté le 23-08-2015 à 20:11:31    

Est-ce que les sous-répertoires peuvent contenir à leur tour des sous-répertoires? Si oui jusqu'à quelle profondeur? Faut-il créer le dossier qui porte la date d'un ou plusieurs fichiers à l'endroit où se trouve le fichier ou plutôt à la racine du truc (là où se trouve le script)? Décris avec précision ce que tu as et ce que tu veux obtenir. Par contre je promets rien, faudra voir si j'ai le temps...

Reply

Marsh Posté le 23-08-2015 à 20:30:06    

Pour ce genre de truc, il y a un module de base standard en perl, File::Find
 
J'aurais fait un script de ce genre:

Code :
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use autodie;
  5.  
  6. use File::Basename;
  7. use File::Find;
  8. use File::stat;
  9.  
  10. $::PROGRAM = basename $0;
  11.  
  12. sub creation_date {
  13.  my $i = 0;
  14.  my @cdate = map {$_ + (0, 1, 1900)[$i++]} (localtime(stat(shift)->ctime))[3..5];
  15.  return sprintf("%04d.%02d.%02d", reverse @cdate);
  16. }
  17.  
  18. sub process {
  19.  if (-f) {
  20.    my $file = $_;
  21.    # on ne traite pas un fichier de même nom que le script
  22.    return if (/^$::PROGRAM$/);
  23.    # on récupère la date de création au format adéquat
  24.    my $cdate = creation_date($file);
  25.    # on ne fait rien si le fichier est déjà dans le bon répertoire
  26.    return if (basename($File::Find::dir) eq $cdate);
  27.    # Arrêt si le répertoire ne peut être créé à cause d'un fichier de même nom
  28.    die "Erreur: le nom '$cdate' est déjà utilisé par un fichier!" if (-f $cdate);
  29.    # On crée le répertoire s'il n'existe pas
  30.    mkdir $cdate unless (-d $cdate);
  31.    # Arrêt si le fichier existe déjà dans le répertoire
  32.    die "Erreur: collision: '$file' existe déjà dans le dossier $cdate!" if (-f $cdate.'/'.$file);
  33.    # on effectue le déplacement du fichier dans le répertoire
  34.    rename $file, $cdate.'/'.$file;
  35.  }
  36. }
  37.  
  38. find({ bydepth => 1, wanted => \&process, follow => 1 }, '.');


(pas testé au delà d'un cas simple avec quelques fichiers, mais ça me semble OK).
Si on veut un message plus explicite pour les messages de sortie en erreur, on peut faire:
die "Erreur: le nom '$cdate' est déjà utilisé par un fichier dans le répertoire $File::Find::dir!"
et
die "Erreur: collision: '$file' existe déjà dans le dossier $File::Find::dir\\$cdate"
 
A+,
 
P.S. pour le rongeur combatif, je ne sais pas si tu connaissais l'idiome employé dans le map, qui sert a ajuster une liste numérique retournée par une fonction, mais il est assez sympa.

Message cité 1 fois
Message édité par gilou le 23-08-2015 à 22:23:36

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 23-08-2015 à 21:10:52    

gilou a écrit :

Pour ce genre de truc, il y a un module de base standard en perl


Il y a un module pour à-peu-près tout en Perl, mais faut le savoir (et faut savoir l'utiliser)... Honnêtement pour moi personnellement j'utilise toujours un truc du genre

Code :
  1. system('dir * /a-d /b > liste');
  2. open(IN, 'liste', '<');
  3. while(($fichier=<IN> ))
  4. ...


 :o

 
Citation :


my @cdate = map {$_ + (0, 1, 1900)[$i++]} (localtime(stat(shift)->ctime))[3..5];

 

P.S. pour le rongeur combatif, je ne sais pas si tu connaissais l'idiome employé dans le map, qui sert a ajuster une liste numérique retournée par une fonction, mais il est assez sympa.


Oulà... Ca c'est encore un truc de "Perl pro". Moi je fais du Perl pour débutant... ;-)

 
Citation :

$::PROGRAM = basename $0;


C'est quoi cette syntaxe $::XYZ?

 

Bon, à priori le problème est réglé...

Message cité 1 fois
Message édité par rat de combat le 23-08-2015 à 21:11:44
Reply

Marsh Posté le 23-08-2015 à 21:38:39    

Effectivement, le problème est réglé. Ca m'a donné envie de me mettre à la programmation...
 
Merci beaucoup pour votre temps.

Reply

Marsh Posté le 23-08-2015 à 22:02:03    

rat de combat a écrit :


Il y a un module pour à-peu-près tout en Perl, mais faut le savoir (et faut savoir l'utiliser)...


Tout a fait, mais File::Find fait partie des trucs très standard. C'est une transposition de la commande find unix
 

rat de combat a écrit :

Citation :

$::PROGRAM = basename $0;


C'est quoi cette syntaxe $::XYZ?

Ça permet d'avoir une variable globale sans faire hurler use strict; :D
Lorsqu'il rencontre  $::XYZ, l'interpréteur sait que c'est une variable dont la portée est le package $main ($:: est une abréviation pour $main::) bref que c'est une variable de package, qui est donc dans un autre namespace que les variables lexicales, pour lesquelles la portée est explicitement indiquée avec l'emploi de my, state, our ou local
 
A+,

Message cité 1 fois
Message édité par gilou le 01-09-2015 à 02:23:56

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 23-08-2015 à 22:26:08    

Note: Pour que le code soit portable sous Unix & Co, j'ai remplacé les deux '\\' par deux '/' dans le code posté précédemment. Ça m'a sauté aux yeux en relisant.
 
A+,


Message édité par gilou le 23-08-2015 à 22:26:32

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 23-08-2015 à 22:26:08   

Reply

Marsh Posté le 31-08-2015 à 16:21:42    

gilou a écrit :


Tout a fait, mais File::Find fait partie des trucs très standard. C'est une transposition de la commande find unix


Moi je ne connais pas (toujours pas) Unix... :o (mais je finirai par m'y mettre, faudra bien)

 
gilou a écrit :

Ça permet d'avoir une variable globale sans faire hurler use strict; :D
Lorsqu'il rencontre  $::XYZ, l'interpréteur sait que c'est une variable dont la portée est le package $main ($:: est une abréviation pour $main::) bref que c'est une variable de package, qui est donc dans un autre namespace que les variables lexicales, pour lesquelles la portée est explicitement indiquée avec l'emploi de my, state, our ou local


Merci pour l'explication!


Message édité par rat de combat le 31-08-2015 à 16:22:23
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed