PERL_Tri et concaténantion

Bonjour,

J'aimerai concaténer plusieurs fichiers ( dans l'ordre) en utilisant le langage PERL ?

Exemple des fichiers à concaténer :

A_1980_AB11_1001.txt
A_1980_AB11_1003.txt
A_1980_AB11_1002.txt
A_1980_2AB12_1001.txt
A_1980_AB13_1001.txt
A_1980_2AB12_1002.txt

Dans le fichier final, je dois avoir le contenu des fichiers ci-dessous ( et dans l'ordre) :

A_1980_AB11_1001.txt
A_1980_AB11_1002.txt
A_1980_AB11_1003.txt
A_1980_2AB12_1001.txt
A_1980_2AB12_1002.txt
A_1980_AB13_1001.txt

Par avance, je vous remercie pour votre aide.

Amine.

7 réponses

Résumé de la discussion

Le besoin est de concaténer plusieurs fichiers en Perl dans un ordre précis, comme A_1980_AB11_1001.txt, A_1980_AB11_1003.txt et A_1980_2AB12_1002.txt, pour produire un fichier final dont le contenu suit un ordre défini. Des solutions évoquées incluent l’énumération des fichiers d’un répertoire, le filtrage par motif tel que A_2012_*, puis le tri pour imposer l’ordre souhaité et l’écriture des contenus dans le fichier de sortie. En pratique, basename et dirname permettent de séparer chemin et nom, et un tri lexicographique via sort peut ordonner les noms selon leur composition numérique, avec des sauts de ligne selon le besoin.

Bobot (l’IA à votre service)
  1. Personne pour m'aider :(((
    0
    1. Bonjour,

      Si tu veut trier tes fichiers, je pense que la meilleur façons de faire est de lister le contenu de ton dossier avec une fonction et ensuite de les trier toi même.
      Une fois que tu les a trié, il ne te reste plus qu'à les ouvrir un par un pour tout entrer dans un seul fichier.

      Une fonction pour lister tous les fichiers d'un dossier :
      sub listDirectory { 
       my ($repertoire) = @_; 
       my @fichiers = (); 
       opendir (my $rep_fh, $repertoire) or die "impossible d'ouvrir le repertoire $repertoire\n"; 
       my @file_rep = grep { !/^\.\.?$/ } readdir($rep_fh); 
       closedir ($rep_fh); 
       foreach my $nom (@file_rep) { 
        if (-f "$repertoire/$nom") { push (@fichiers, $nom); } 
       } 
       return @fichiers; 
      }
      0
      1. Merci beaucoup pour cette réponse. malheureusement, je ne suis pas un spécialiste du PERL et ne comprends pas l'ensemble de votre programme.

        Pour exécuter votre programme, je dois :
        - Définir une variable "repertoire" : \\Home\TEST
        - Définir la variable "fichiers" ( le répertoire final)

        Est-ce que c'est bien ça ?

        Encore, je vous remercie beaucoup.

        sub listDirectory {
        my ($repertoire) = @_;
        my @fichiers = ();
        opendir (my $rep_fh, $repertoire) or die "impossible d'ouvrir le repertoire $repertoire\n";
        my @file_rep = grep { !/^\.\.?$/ } readdir($rep_fh);
        closedir ($rep_fh);
        foreach my $nom (@file_rep) {
        if (-f "$repertoire/$nom") { push (@fichiers, $nom); }
        }
        return @fichiers;
        }
        0
        1. Il suffit de lancer la fonction avec comme ceci :
          my $repertoire = "TON DOSSIER";
          my @fichiers = &listDirectory($repertoire);

          Sachant que la variable $repertoire contient le chemin vers le dossier que tu veut lister.
          Ensuite, la fonction va te retourner un tableau (@fichiers) qui contient tous les fichiers du dossier.
          0
          1. Salut,

            J'ai écrit le code en Python.

            J'ai d'abord créé 6 fichiers avec les contenus suivants:

            - nom du fichier: AB11_1001
            - contenu du fichier:
            blablabli
            blablabla
            contenu du fichier AB11_1001
            balablabalablalblabli

            - nom du fichier: AB11_1003
            - contenu du fichier:
            karakako
            contenu du fichier AB11_1003
            kakakukiko

            - nom du fichier: AB11_1002
            - contenu du fichier:
            dudurududu
            contenu du fichier AB11_1002
            dododudud

            - nom du fichier: 2AB12_1001
            - contenu du fichier:
            mumumumimimim
            contenu du fichier 2AB12_1001
            mamamamimummmumim

            - nom du fichier: AB13_1001
            - contenu du fichier:
            xixixixixixixixixi
            contenu du fichier AB13_1001
            xuxuxuxuuxxuxexexexexe

            - nom du fichier: 2AB12_1002
            - contenu du fichier:
            taratatattat
            ttatrotototerottotot
            contenu du fichier 2AB12_1002
            tttttttaaaaaaratatatatta

            Et le code qui crée un fichier cumulatif des contenus de ces fichiers dans un ordre dépendant de leur nom:

            from os import listdir 
            import re 
            
            regx = re.compile('[_\d]+(?=\.)') 
            
            li = listdir('I:\\Prov Python') 
            li.sort(key=lambda x: regx.search(x).group()) 
            
            with open('I:\\Prov Python\\cumul.txt','w') as cumul: 
                for filename in li: 
                    with open('I:\\Prov Python\\' + filename,'r') as f: 
                        cumul.write(f.read())


            Bien sûr, la regex est fonction de ce que j'ai pensé plausible comme critère de tri des noms de fichiers sur la base de seulement 6 noms. Pour d'autres règles, il faudra une regex différente.

            Après exécution, j'obtiens le fichier cumul.txt avec le contenu suivant:

            blablabli
            blablabla
            contenu du fichier AB11_1001
            balablabalablalblabli

            dudurududu
            contenu du fichier AB11_1002
            dododudud

            karakako
            contenu du fichier AB11_1003
            kakakukiko

            mumumumimimim
            contenu du fichier 2AB12_1001
            mamamamimummmumim

            taratatattat
            ttatrotototerottotot
            contenu du fichier 2AB12_1002
            tttttttaaaaaaratatatatta

            xixixixixixixixixi
            contenu du fichier AB13_1001
            xuxuxuxuuxxuxexexexexe

            Je sais que tu as parlé de Perl, mais comme tu dis ne pas le connaître, ce n'est peut être que l'objectif qui t'intéresse, sans être attaché à un langage en particulier.
            0
            1. Je pense que je n'ai pas très bien décris le besoin :
              le but est de concatener le contenu des fichiers et à voir un "fichier_concat_final" qui contient le contenu de l'ensemble des fichiers.

              Merci encore pour votre aide.
              0
              1. C'est exactement ce que viens de te proposer heyquem, il récupère le contenu de tous tes fichiers pour le mettre dans un fichier cumul.txt.
                0
              2. Merci de m'avoir compris valentin :)
                0
              3. Bonjour heyquem,

                MERCI pour votre aide. Je n'avais pas vu votre poste.
                Mlaheureusement, j'ai absolument besoin de le faire en PERL :(
                0
              4. Malheureusement pour toi en Perl ça va être plus compliqué ^^
                Voila un bout de code pour t'aider :

                #!/usr/bin/perl   
                use warnings;   
                use strict;   
                
                sub listDirectory {    
                 my ($repertoire) = @_;    
                 my @fichiers = ();    
                 opendir (my $rep_fh, $repertoire) or die "impossible d'ouvrir le repertoire $repertoire\n";    
                 my @file_rep = grep { !/^\.\.?$/ } readdir($rep_fh);    
                 closedir ($rep_fh);    
                 foreach my $nom (@file_rep) {   
                  if (-f "$repertoire/$nom") { push (@fichiers, $nom); }    
                 }   
                 return @fichiers;    
                }   
                
                my $repertoire = "TON DOSSIER"; # Répertoire qui contient tes fichiers   
                my @fichiers = &listDirectory($repertoire);   # Tableau avec tous tes fichiers   
                my $lengthFichiers = scalar @fichiers;    # Taille du tableau   
                
                # TRIER LE TABLEAU SELON TES PARAMETRES   
                
                # Ecrire dans le fichier de sortie   
                my $finalFile = "fichier_concat_final.txt";   
                open(ECRIRE, ">$finalFile") || die ("Erreur d'ouverture de $finalFile");   
                
                for(my $i = 0; $i < $lengthFichiers; $i++) {   
                 my $currentFile = $repertoire . "/" . $fichiers[$i];   
                 open(LIRE, $currentFile) || die ("Erreur d'ouverture de $currentFile");   
                 while(<LIRE>) { print ECRIRE $_; }   
                 close(LIRE);   
                }   
                
                close(ECRIRE);


                Et oui le perl c'est pas très esthétique :D
                La partie la plus compliquer va être de trier le tableau selon tes paramètres, voici un lien pour t'aider http://articles.mongueurs.net/magazines/linuxmag48.html
                En espérant que ça t'aide.

                Edit : Je suis sur un système linux, à toi d'adapter le dossier si tu est sur windows
                0
              5. Tant pis pour toi ! :))
                0
            2. J'ai encore une question :)

              Le programme ci-dessus, lit tous les fichiers se trouvant dans "le répertoire". or moi, j'aurai besoin de lire seulement les fichier començant par une chaine de caractères, par exemple : A_2012_*

              Merci pour votre retour.
              0
              1. Il faut utiliser les regex pour traiter les fichiers récupérés.
                Par exemple :
                if($fichier =~ m/A_2012_(.*)/) { OK }
                0
              2. Voila ce que ça donne dans ton cas :
                sub listDirectory { 
                 my ($repertoire) = @_; 
                 my @fichiers = (); 
                 opendir (my $rep_fh, $repertoire) or die "impossible d'ouvrir le repertoire $repertoire\n"; 
                 my @file_rep = grep { !/^\.\.?$/ } readdir($rep_fh); 
                 closedir ($rep_fh); 
                 foreach my $nom (@file_rep) { 
                  if (-f "$repertoire/$nom") {
                   # Si le fichier est sous la forme A_2012_*, alors on le prend en compte
                   if($nom =~ m/A_2012_(.*)/) { push (@fichiers, $nom); }
                  } 
                 } 
                 return @fichiers; 
                }
                0
              3. @Valentin: Again, MERCI beauacoup pour votre aide.

                Bonne soirée
                0
              4. Bonjour,

                J'ai encore une autre question :
                Comment peut-on tester l'existence des fichiers commençant par "A_2010_*" ?

                J'ai essayé le code ci-dessous, mais malheureusement ça ne marche pas. Pourriez-vous m'aider ?

                Merci à vous !

                if ( -e "A_2010_*")
                {
                }
                0
              5. Re-bonjour,

                Pour tester l'éxistance d'un fichier, il faut utiliser la commande if(-f FICHIER).
                Donc si tu veut tester l'éxistance d'un fichier commençant par A_2010_* il faut combiner ton teste avec la regex suivante : my $file =~ m/^A_2010_(.*)/;
                Ce qui te donne :
                if( -f $file) { #FICHIER EXISTE } else { #FICHIER N EXISTE PAS }
                0