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

C Discussion :

recherche dans un dossier


Sujet :

C

  1. #1
    Membre du Club
    Homme Profil pro
    Ingénieur c++ junior
    Inscrit en
    Mai 2013
    Messages
    35
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Ingénieur c++ junior
    Secteur : Santé

    Informations forums :
    Inscription : Mai 2013
    Messages : 35
    Points : 41
    Points
    41
    Par défaut recherche dans un dossier
    Bonjour

    Je voudrais réaliser un programme en c qui me permet de rechercher tous les fichiers qui suivent le motif d'une expression régulière dans un dossier et tous ses sous-dossier je les stocke ensuite leur nom et chemin dans une liste.
    j'utilise la librairie regex.h pour utiliser les expressions régulières et dirent.h pour naviguer dans les dossier.
    Le debugage au printf m'a permit de voir que l'erreur se trouve dans ma fonction parcours_directory. Voici mon code
    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
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    #include <stdio.h>
    #include <stdlib.h>
    #include <regex.h>
    #include <dirent.h>
    #include "projet.h"
    #include <link.h>
    #include <string.h>
     
     
    int isDir(struct dirent* currentFile)
    {
        if ((strchr(currentFile->d_name, '.')) == NULL) /* Si le nom du fichier n'a pas de point (une extension). */
            return 1;
        else
            return 0;
    }
     
    char* concatpath(char *s1,char *s2)
    	{
         char *s3=NULL;
         s3=(char *)malloc((strlen(s1)+strlen(s2))*sizeof(char));
         strcpy(s3,s1);
    	 strcat(s3,"\\");
         strcat(s3,s2);
         return s3;
    	}
     
     
    int parcours_directory (DIR* rep, regex_t exp, char* path, struct link* l )
    {	int cpt = 0; //compteur pour debugger
    	struct dirent* currentFile;
    	int match;
    	while ((currentFile = readdir(rep)) != NULL)
    		{
    		++cpt;
    		printf("toto parcours 1\n %d\n", cpt);
    		if (isDir(currentFile))
    			{
    			printf("toto parcours 2\n %d\n", cpt);
    			path=concatpath(path, currentFile->d_name); // on met à jour le path
    			rep = opendir(path);
    			parcours_directory(rep, exp, path, l);
    			closedir(rep);
    			}
    		if ((match = regexec (&exp, currentFile->d_name,0, NULL, 0)) == 1)
    			{
    			struct lelement* e;
    			printf("toto parcours 3\n %d\n", cpt);
    			e = create_lelement(currentFile->d_name, path);
    			lnk__add_head(l,e); // on stock dans la  link
    			display_lnk(l);
    			}
    		}
    	return 0;	
    }
     
    int main (int argc, char *argv[]) // argument 1 = chemin racine, argument 2 = expression régulière à chercher
    {
     
        DIR* rep;
        regex_t exp;
        const char* str_regex = argv[2];
        char* path = argv[1];
        struct link* l = lnk__empty();
    	printf("%d", argc);
        if (argc != 3)
        {
                printf(" les arguments doivent etre valides : argument 1 = chemin racin, argument = expression reguliere a chercher.");
                    return 0;
        }
     
    	rep = opendir(path);
    	printf("toto\n");
    	regcomp (&exp, str_regex, REG_NOSUB | REG_EXTENDED); // compilation de l'expression régulière
    	parcours_directory(rep, exp, path, l);
    	printf("tot1");
    	display_lnk(l);
    	regfree (&exp);
    	lnk_free(l);
    	free(path);
        return 0;
    }
    voici mon tad de liste, c'est peu être qui pose problème, mais je ne pense pas.
    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
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    #include "link.h"
     
     
     
     
    struct lelement *create_lelement( char* name, char* path)
    {
    	struct lelement* e = malloc (sizeof(struct lelement));
    	e->name = name;
    	e->path = path;
    	e->next = NULL;
            return e;
    }
     
    struct link* lnk__empty()
    {
    	struct link* l = malloc (sizeof(struct link));
    	l->head = NULL;
    	return l; 
    }
     
     
    int lnk__is_end_mark(struct lelement *e)
    {
      return (e == NULL);
    }
     
    void lnk__add_head(struct link *l, struct lelement *e)
    {
      e->next = l->head;
      l->head = e;
    }
     
    struct lelement *lnk__remove_head(struct link *l)
    {
      struct lelement *tmp = l->head;
      l->head = l->head->next;
      return tmp;
    }
     
     
    void display_lnk (struct link* l)
    {
    	struct lelement *tmp;
    	for(tmp = l->head; !lnk__is_end_mark(tmp->next); tmp = tmp->next)
    	{
    		printf("%s à pour chemin %s\n", tmp->name, tmp->path);
    	}
    } 
     
    void lnk_free(struct link* l)
    {
            struct lelement* tmp;
    	for(tmp = l->head; !lnk__is_end_mark(tmp->next); tmp = tmp->next)
    		free(tmp);
    	free(l);
    }

    Merci pour votre futur aide
    Amicalement Psykomusic.

  2. #2
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Attention à l'aliasing! Tous tes éléments seront créés avec le même buffer path...

    Sans compter que tu pointes directement sur le chemin de fichier de la structure dirent, dont tu ne contrôles même pas la durée de vie!
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Membre du Club
    Homme Profil pro
    Ingénieur c++ junior
    Inscrit en
    Mai 2013
    Messages
    35
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Ingénieur c++ junior
    Secteur : Santé

    Informations forums :
    Inscription : Mai 2013
    Messages : 35
    Points : 41
    Points
    41
    Par défaut
    C'est la première fois que j'utilise les biblios dirent et regex et je n'ai pas compris ta réponse ^^

  4. #4
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Cette ligne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    e = create_lelement(currentFile->d_name, path);
    La fonction create_lelement() ne copie pas le buffer: Elle mémorise seulement le pointeur d_name, sur lequel tu n'as pas de contrôle.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  5. #5
    Membre du Club
    Homme Profil pro
    Ingénieur c++ junior
    Inscrit en
    Mai 2013
    Messages
    35
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Ingénieur c++ junior
    Secteur : Santé

    Informations forums :
    Inscription : Mai 2013
    Messages : 35
    Points : 41
    Points
    41
    Par défaut
    yep, je vais passer par une variable intermédiaire afin de ne pas filer le pointeur à mon élément, mais bien la chaine de caractère.

  6. #6
    Membre confirmé
    Homme Profil pro
    amateur
    Inscrit en
    Octobre 2007
    Messages
    731
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : amateur

    Informations forums :
    Inscription : Octobre 2007
    Messages : 731
    Points : 460
    Points
    460
    Par défaut
    Pour ma part, j'utilise dirent de la façon suivante pour effectuer une recherche réursive d'un fichier depuis un répertoire racine.
    Je me contente de matcher un nom, pas de pattern. La où je fais le contrôle du nom du fichier(surligné en rouge), cela pourrait être ton regex.

    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
    31
    32
    33
    char *directory_search_entity(char *directory_path, char *entity_name)
    {
        DIR *directory = NULL;
        char *entity_path = NULL;
        if ( !(entity_path = directory_search_entity_recursive(directory, directory_path, entity_name)) )
            fprintf(logger,"\ndir.h::directory_search_entity -> The %s file has not been found in the %s directory", entity_name, entity_path);
    
        return entity_path;
    }
    
    char *directory_search_entity_recursive(DIR *directory, char *directory_path, char *entity_name)
    {
        directory = directory_open(directory_path);
        struct dirent *entity=NULL;
        seekdir(directory,2);
        char *entity_path = NULL;
        while((entity=readdir(directory)))
        {
            entity_path = get_entity_path(directory_path, entity->d_name);
            if (is_directory(entity_path))
                directory_search_entity_recursive(directory, entity_path, entity_name);
    
            else
            {
                if (strcmp( entity->d_name, entity_name )==0)                
                            while((entity=readdir(directory)));
    
                else deallocate_1D_c(entity_path);
            }
        }
        directory_close(directory);
        return entity_path;
    }
    UNE REPONSE UTILE : &|| UN PROBLEME RESOLU :

  7. #7
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    J'ai l'impression qu'il y a des chaînes qui manquent de const, là-dedans...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  8. #8
    Membre du Club
    Homme Profil pro
    Ingénieur c++ junior
    Inscrit en
    Mai 2013
    Messages
    35
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Ingénieur c++ junior
    Secteur : Santé

    Informations forums :
    Inscription : Mai 2013
    Messages : 35
    Points : 41
    Points
    41
    Par défaut
    après avoir modifié la construction de l'élément en passant par une variable tampon, j'ai toujours le même probleme, le programme crash après avoir tout visité.
    Voici ma modification :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    struct lelement* e;
    	char* tmp;
    	strcpy(tmp, currentFile->d_name);
    	e = create_lelement(tmp, path);

    edit : j'ai ajouté un closedir(rep) entre les lignes 40 et 41 il va plus loin, cependant le match entre toto1.txt et t*.txt renvoie 0 et après ça plante.
    edit2: j'ai enlever le closedir ligne 43, une petite modification dans free_lnk qui finalement marchait mal et le programme ne segfault plus. Seulement, je n'arrive pas à avoir de match entre les fichiers courant ( dans mon cas toto1.txt et toto2.txt avec la regex prise en argument t*.txt)

  9. #9
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Tu copies vers un pointeur non-initialisé.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  10. #10
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Le mieux, c'est de modifier create_lelement() ainsi, pour tout mettre dans le même malloc() et recopier les chaînes:
    Code C : 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
    struct lelement * create_lelement( char const * name, char const * path )
    {
    	size_t nameSize = (name==NULL ? 0 : strlen(name)+1);
    	size_t pathSize = (path==NULL ? 0 : strlen(path)+1);
     
    	struct lelement* pe = malloc (sizeof(struct lelement) + nameSize + pathSize);
    	if(pe != NULL)
    	{
    		char *pFirstChar = (char*)(pe+1); /*pointe just après la structure element (pas de prob d'alignement vu que c'est des char)*/
    		pe->next = NULL;
    		if(name != NULL)
    		{
    			pe->name = pFirstChar + 0; /*name pointe just après la structure element*/
    			strncpy(pe->name, name, nameSize-1);
    			pe->name[nameSize-1] = '\0';
    		}
    		if(path != NULL)
    		{
    			pe->path = pFirstChar + nameSize; /*path pointe just après le buffer de name*/
    			strncpy(pe->path, path, pathSize-1);
    			pe->path[pathSize-1] = '\0';
    		}
    	}
    	return pe;
    }
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  11. #11
    Membre du Club
    Homme Profil pro
    Ingénieur c++ junior
    Inscrit en
    Mai 2013
    Messages
    35
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Ingénieur c++ junior
    Secteur : Santé

    Informations forums :
    Inscription : Mai 2013
    Messages : 35
    Points : 41
    Points
    41
    Par défaut
    Merci pour tes réponses !
    Ne faut-il pas retourner pe plutôt que e ?

  12. #12
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Citation Envoyé par psykomusic Voir le message
    Ne faut-il pas retourner pe plutôt que e ?
    Corrigé
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  13. #13
    Membre du Club
    Homme Profil pro
    Ingénieur c++ junior
    Inscrit en
    Mai 2013
    Messages
    35
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Ingénieur c++ junior
    Secteur : Santé

    Informations forums :
    Inscription : Mai 2013
    Messages : 35
    Points : 41
    Points
    41
    Par défaut
    Bon Alors j'ai toujours un problème ^^
    Quand je reviens recursivement dans un dossier parent, mon pointeur CurrentFile garde l'ancienne valeur.
    par exemple j'ai un dossier test qui contient toto.txt et un dossier test2 qui contient un fichier toto2.txt de cette manière :
    toto1.txt = test\toto1.txt
    toto2.txt = test\test2\toto2.txt

    Ma fonction rentre dans test2, ajoute toto2 à ma liste, puis revient en arrière, seulement CurrentFile pointe toujours sur test2, currentFile = readdir(rep) retourne donc NULL et ma boucle while(currentFile =! NULL) s’arrête car il n'y a plus rien à visiter dans test2, toto1 n'est donc jamais considérer par mon programme...
    j'ai aussi toujours un erreur mémoire que je n'arrive pas à identifier

Discussions similaires

  1. recherche dans un dossier
    Par champenois51 dans le forum Word
    Réponses: 1
    Dernier message: 29/12/2013, 18h05
  2. [AppleScript] Rechercher dans un dossier du Finder
    Par iLandes dans le forum AppleScript
    Réponses: 1
    Dernier message: 17/01/2011, 20h29
  3. Réponses: 0
    Dernier message: 17/05/2010, 10h43
  4. [BATCH] Recherche dans sous-dossiers
    Par tonf dans le forum Scripts/Batch
    Réponses: 9
    Dernier message: 13/08/2008, 15h17
  5. Recherche d'un dossier dans le disque
    Par com-ace dans le forum Access
    Réponses: 6
    Dernier message: 31/08/2006, 10h51

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