Ecriture et suppression dans un fichier

Ecriture et suppression dans un fichier - Perl - Programmation

Marsh Posté le 06-11-2014 à 17:43:20    

Bonjour,
 
Le but de mon programme est de scanner des répertoires et inscrire dans un fichier texte tous les fichiers trouvés.
 
Le script s'exécute plusieurs fois par jour. Dès qu'un nouveau fichier est ajouté dans un répertoire, le script doit l'ajouter dans le fichier texte.
Et à l'inverse si un fichier est supprimé d'un répertoire, si celui-ci est présent dans le fichier texte, il doit également être supprimé du fichier texte lors du passage du script.
 
Mon soucis avec le code ci-dessous est que le script ajoute bien les fichiers mais ne les suppriment jamais !
 

Code :
  1. #!/usr/bin/perl
  2. use warnings;
  3. use autodie;
  4. use File::Find;
  5. use Cwd;
  6. use POSIX qw/strftime/;
  7. #Recuperation date du jour
  8. my $date = strftime("%Y%m%d", localtime());
  9. #Creation fichier temporaire
  10. my $filename = "D:\\report_$date.txt";
  11. if (!-f $filename) {
  12.   open(ECRIRE,">$filename" );
  13.   close (ECRIRE);
  14. }
  15. my $dir = "C:\\temp";
  16. find( \&search, $dir );
  17. sub search {
  18.   if (-f "$_" ) {
  19.     my @keywords = $_;
  20.     my %kwfound;
  21.     open my $fh, "+<", $filename;
  22.     while (<$fh> ) {
  23.       s/\n$//o;
  24.       foreach my $kw (@keywords) {
  25.         if ($_ eq $kw) {
  26.           ++$kwfound{$kw};
  27.         }
  28.       }
  29.     }
  30.       foreach my $kw (@keywords) {
  31.         if (!defined($kwfound{$kw})) {
  32.           print $fh "${kw}\n";
  33.         } else {
  34.             print "Fichier $kw deja present $filename\n";
  35.         }
  36.       }
  37. close $fh;
  38.   }
  39. }


 
Est-ce que quelqu'un aurait une petite idée svp pour supprimer les fichiers du fichier texte lors qu'ils sont supprimés du répertoire ?
 
Merci d'avance.

Reply

Marsh Posté le 06-11-2014 à 17:43:20   

Reply

Marsh Posté le 06-11-2014 à 22:19:37    

C'est totalement inefficace ce script, tu parcours ton fichier a chaque appel de search [:darkmavis tt]  
 
En plus cette ligne ci est complétement fausse: my @keywords = $_; $_ est le nom du fichier en cours pour search, ce n'est pas une liste, et il y a d'autres choses pas très casher.
 
Vu ce que tu veux faire, il suffit de réécrire le fichier a neuf a chaque fois que tu le veux, non?
La seule chose qui justifierais ton approche, c'est que l'ordre des fichiers soit importante, et que les nouveaux fichiers soient ajoutés en fin de fichier. Est-ce le cas? parce que sinon, aucune raison de se compliquer la vie.
 
A+,


Message édité par gilou le 06-11-2014 à 22:21:59

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

Marsh Posté le 07-11-2014 à 11:02:17    

Bonjour,
 
Le réécrire à chaque fois, non je ne pense pas !
 
Comment ça marche :
1 - Je parcours l'ensemble d'un répertoire avec sous répertoire.
2 - Je mets dans un fichier texte tous les fichiers trouvés.
3 - Le script se réexécute.
4 - A chaque nouveau fichier qui ne se trouve pas dans le fichier texte, je l'ajoute dedans.
5 - Si le fichier trouvé est déjà présent dans le fichier texte alors j'indique par un message comme quoi le fichier existait déjà précédemment.
 
Si ce n'est pas assez clair, n'hésite pas à me demander.
Merci en tout cas pour ta réponse.

Reply

Marsh Posté le 07-11-2014 à 16:58:46    

Bien sur que si que tu vas le réécrire a chaque fois. Ne serait-ce qu'a cause des suppressions de texte.

Citation :

Si le fichier trouvé est déjà présent dans le fichier texte alors j'indique par un message comme quoi le fichier existait déjà précédemment.


S'il y a que cela, de spécial...
 
1) tu lis ton fichier, tu mets chaque nom de fichier comme clé d'un hash
2) tu réécris ton fichier en procédant ainsi: tu parcours ton répertoire avec search
    Pour chaque fichier trouvé,  
    soit il est clé du hash fabriqué en 1, et tu l'écris dans le fichier en indiquant qu'il s'y trouvait précédemment
    soit il n'est pas clé, et tu l'écris dans le fichier  
 
Bref c'est qque chose comme ceci (à adapter à tes besoins):

Code :
  1. use strict;
  2. use warnings;
  3. use File::Find;
  4.  
  5. my $filename = "D:\\report_$date.txt";
  6. my ($fh, %oldfiles);
  7. if (-f $filename) {
  8.  open $fh, "<", $filename;
  9.  %oldfiles = map {s/(\s:Fichier deja present dans $filename)?\n$//o;($_, 0)} <$fh>;
  10.  close $fh;
  11. }
  12.  
  13. open $fh, "+>", $filename;
  14. my $dir = "C:\\temp";
  15. find( \&search, $dir );
  16. sub search {
  17.  if (-f "$_" ) {
  18.    if (defined $oldfiles{$File::Find::name}) {
  19.        print $fh "$File::Find::name :Fichier deja present dans $filename\n";
  20.    }
  21.    else {
  22.      print $fh "$File::Find::name\n";
  23.    }
  24.  }
  25. }
  26. close $fh;


J'utilise le nom relatif au dossier donné en argument $File::Find::name afin d'avoir un nom de fichier unique utilisable comme clé (bon, s'il y a pas de sous répertoires, ou si on est sur que les noms de fichiers (sans path) sont uniques, on peut utiliser $_ directement).
 
A+,


Message édité par gilou le 07-11-2014 à 17:08:54

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

Marsh Posté le 11-11-2014 à 11:28:11    

Bonjour Gilou et merci encore une fois.
 
J'eesaye d'adapté le code à mes besoins car tout ne fonctionne pas quand je le ré-exécute plusieurs fois ! J'ai le message suivant :
 
Unrecognized escape \T passed through in regex; marked by <-- HERE in m/(\s:Fichier deja present dans D:\x128115\T <-- HERE ravail
\report_20141110.txt)?\n$/ at D:\x128115\scripts\Perl\test_3.pl line 15, <$_[...]> line 5.
 
Par contre de ce que j'ai compris : Dans ton code si le fichier est déja présent dans le fichier texte, il inscrit dans celui-ci ! Mon souhait c'était de l'afficher à l'écran.
 
Et pourrais tu stp m'expliquer justement ce que fait exactement la fonction "map" ?
 
Merci d'avance.

Reply

Marsh Posté le 11-11-2014 à 15:35:38    

> Unrecognized escape \T passed through in regex
C'est parce que tu as des \ dans tes noms de fichiers et que tu mes a pas escapés dans la regexp.
m/(\s:Fichier deja present dans D:\\x128115\\T...
Mais il vaudrait beaucoup mieux écrire D:/x128115//T... parce que $File::Find::name est construit a partir de ton nom de répertoire (donc avec des / ou des \\ selon ce que tu as passé) suivi de / suivi du nom de fichier, et un mélange de \\ et / c'est pas beau et ça peut mener à des problèmes.
 
> Mon souhait c'était de l'afficher à l'écran.  
C'est encore plus facile alors, il suffit de faire  
 

Code :
  1. use strict;
  2.    use warnings;
  3.    use File::Find;
  4.    
  5.    my $filename = "D:/report_$date.txt";
  6.    my ($fh, %oldfiles);
  7.    if (-f $filename) {
  8.     open $fh, "<", $filename;
  9.     %oldfiles = map {s/\n$//o;($_, 0)} <$fh>;
  10.     close $fh;
  11.    }
  12.    
  13.    open $fh, "+>", $filename;
  14.    my $dir = "C:/temp";
  15.    find( \&search, $dir );
  16.    sub search {
  17.     if (-f "$_" ) {
  18.       if (defined $oldfiles{$File::Find::name}) {
  19.           print "$File::Find::name :Fichier deja present dans $filename\n";
  20.       }
  21.       print $fh "$File::Find::name\n";
  22.     }
  23.    }
  24.    close $fh;


 
> Et pourrais tu stp m'expliquer justement ce que fait exactement la fonction "map" ?  
map ça prend un bloc et une liste en entrée et ça retourne la liste constituée de l'évaluation du bloc pour chaque élément de la liste.
map {uc($_)} ("toto", "tata" ); ça va renvoyer la liste ("TOTO", "TATA" )
 
A+,


Message édité par gilou le 11-11-2014 à 15:39:39

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

Marsh Posté le 18-11-2014 à 11:29:40    

Bonjour Gilou,
 
Désolé de te répondre aussi tardivement mais je n'ai pas eu le temps de tester avant.
 
Donc je te remercie beaucoup car c'est exactement ce que je voulais faire.
 
@+

Reply

Sujets relatifs:

Leave a Replay

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