IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Modules Perl Discussion :

Utilisation du module File::Find


Sujet :

Modules Perl

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    101
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 101
    Points : 59
    Points
    59
    Par défaut Utilisation du module File::Find
    Bonjour à tous,


    Je suis débutant en Perl et je cherche à classifier les fichiers d'une arborescence donnée, mais je n'arrive pas à les trier de manière performante par "type", puis par "nom".

    Voici le code que j'utilise :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
     
    open( RECAP , ">$recap_pcstxml" )
    or die "Ouverture du fichier $recap_pcstxml impossible : $!\n";
     
    print RECAP q(<?xml version="1.0"?>
    <!DOCTYPE Recap SYSTEM "recap.dtd">
     
    <Recap name="packName" version="1.2">
    );
     
     
    find( \&genpcstxml, $root_pcst );
     
    print RECAP q(
    </Recap>
    );
     
    close( RECAP );
     
     
    sub genpcstxml {
      return if -d;     # exclusion des répertoires
     
      my $hostPath = $File::Find::dir;
     
      print RECAP qq(
      <File name="$_" hostPath="$hostPath" >
      </File>);
     
    }

    Avec ce code j'obtiens une classification par "nom" (et non "type" puis "nom"), par répertoire.

    Merci d'avance pour vos réponses.

  2. #2
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Qu'entends-tu par type ?
    - fichier/directory/block
    - type genre MIME ?
    - type comme le retour de la commande U*ix file ?
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    101
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 101
    Points : 59
    Points
    59
    Par défaut
    Merci pour t'as réponse Philou,

    Désolé je n'ai pas été très explicite.
    J'entends par type, l'extension du fichier (exemple : toto.bat)
    Je voudrais donc classer les fichier dans une directory donnée par extension de type de fichier puis par nom de fichier.

    Pour l'instant je classe par directory puis par nom.

  4. #4
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Dans ce cas, je te propose la chose suivante :
    La callback de Find::File remplit un tableau contenant les noms de fichiers (ou plus précisément, une structure sous forme d'un tableau contenant les éléments de tri d'un fichier : chemin, nom, extension ; il est facile de les obtenir à l'aide du module File::Basename).
    Ensuite, tu utilises sort avec une procédure de tri spécifique.

    Voici ce que cela pourrais donner (sans la mise en forme que tu pourras ajouter toi même) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #!/usr/bin/perl
     
    use strict;
    use warnings;
    use File::Basename qw(fileparse);
    use File::Find qw(find);
     
    my @files;
    print "Searching for files in $ARGV[0]\n";
    # Attention : fileparse sépare le fichier en "nom", "chemin", "extension" dans cet ordre
    find(sub { push @files, [ fileparse $File::Find::name, qr/\.[^.]*/ ] }, $ARGV[0]);
    my @sorted_files = map { join "", @$_[qw(1 0 2)] } sort { $a->[1] cmp $b->[1] || $a->[2] cmp $b->[2] || $a->[0] cmp $b->[0] } @files;
    print join "\n", @sorted_files, "\n";
    J'ai testé ce code, et à priori, il fonctionne.
    Si tu as des questions complémentaires, n'hésite pas une seconde.
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    101
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 101
    Points : 59
    Points
    59
    Par défaut
    Merci pour t'as réponse si rapide.

    J'ai oublié de préciser, que je travail sur une plateforme "Windows"...

    Je viens d'intégrer ton code pour tenter de comprendre les subtilités (c'est pas gagné... ).

    Voici le message que j'obtiens :

    Can't use "my $a" in sort comparison at liva2k.pl line 695.
    La ligne 695 correspond à :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    my @sorted_files = map { join "", @$_[qw(1 0 2)] } sort { $a->[1] cmp $b->[1] || $a->[2] cmp $b->[2] || $a->[0] cmp $b->[0] } @files;
    Je ne comprends pas d'ou vient le problème, d'autant plus que j'ai du mal à comprendre l'enchainement des fonctions "map, join et sort".

  6. #6
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    L'enchainement des join, map et sort est une sorte de pipeline "à l'envers".

    Comme le dernier argument de chacune des fonctions join, map et sort est une liste, et que map et sort fournissent en retour des listes, il est possible de les enchainer les unes à la suite, la première exécutée étant la dernière dans la file.

    Ainsi, le sort agit d'abord sur @files et retourne une liste de références de tableau triée, puis map prend cette liste de référence et reconstruit un nom sous forme de chaine de caractère en concaténant les 3 éléments du tableau, dans le bon ordre, et enfin, join rassemble le tout pour l'affichage.

    Je ne comprends pas ton erreur : as-tu introduit une déclaration my $a dans la procédure de tri de la fonction sort ?
    Quelle version de perl utilises-tu ?
    Ce code fonctionne sur ma plateforme (Windows/Cygwin).
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    101
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 101
    Points : 59
    Points
    59
    Par défaut
    Bien vu Philou :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Je ne comprends pas ton erreur : as-tu introduit une déclaration my $a dans la procédure de tri de la fonction sort ?
    Il y avait une variable $a de déclarée dans une partie du code (dont je n'étais pas l'auteur).

    Visiblement le code que tu as proposé semble correspondre à mon besoin !
    Je fais quelques vérification supplémentaire...

    Par contre, je ne comprend pas le méchanisme de cette partie :

    Pourrais-tu m'expliquer ?

  8. #8
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Bien sur :

    Le sigil @ en début d'expression indique que je déréférence un tableau.
    On trouve ensuite $_, qui correspond à la référence de notre tableau de trois valeurs.
    Pour prendre la première valeur du tableau, on aurait écrit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $$_[0]; # (ou de manière plus élégante $_->[0])
    Dans notre cas, on souhaite récupérer les trois valeurs. On aurait donc pu écrire simplement :
    Oui mais voila, les valeurs ne sont pas ordonnées comme on le souhaite. Il faut donc retourner un tableau donc on va spécifier l'ordre des éléments.

    On peut donc écrire une liste de 3 éléments :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $_->[1], $_->[0], $_->[2]
    Ou bien encore :
    Cette dernière écrire peut générer des ambiguités (me semble-t-il), ce qui fait que je lui préfère
    l'opérateur qw() générant de façon sure une liste des valeurs fournies en paramètre et séparés par des espaces.
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    101
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 101
    Points : 59
    Points
    59
    Par défaut
    Un grand MERCI a toi Philou !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 3
    Dernier message: 10/04/2008, 14h02
  2. Problème d'utilisation de File::Find
    Par jotape75 dans le forum Modules
    Réponses: 2
    Dernier message: 05/06/2007, 09h51
  3. [web] Probleme de passe de variable qd j utilise un module TK
    Par Slippers dans le forum Interfaces Graphiques
    Réponses: 5
    Dernier message: 19/04/2005, 17h48
  4. [HTML]Utilisation du type file
    Par Kuroro dans le forum Balisage (X)HTML et validation W3C
    Réponses: 7
    Dernier message: 23/12/2004, 16h12
  5. Probleme de perf avec File::Find::name;
    Par Ludo167 dans le forum Modules
    Réponses: 6
    Dernier message: 14/07/2004, 11h31

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo