Parcours récursif d'un repertoire

Signaler
Messages postés
10
Date d'inscription
samedi 15 mai 2004
Statut
Membre
Dernière intervention
16 mai 2004
-
Messages postés
3011
Date d'inscription
jeudi 26 septembre 2002
Statut
Membre
Dernière intervention
27 novembre 2004
-
mon parcours ne fonctionne que pour le repertoire passé en parametre
et pour ses sous repertoire.. mais il ne vas pas au delas dans l'arborescence.. je voudrais qu'il explore les repertoire des
sous repertoies etc...
voila mon code:

#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include



//-- Fonction recursive qui Affiche le contenu du repertoire --//

void parcoursRep(char *rep){

//chaine de caractere a afficher pour chaque entree
char *nom;

//longueur de cette chaine
int nomTaille;

//flux repertoire
DIR *dir;

//une entree du repertoire
struct dirent *entree;

//structure contenant les informations d'une entree
struct stat infosEntree;

//indice de defilement dans listeEntrees
int n;

//nombre d'entre du repertoire
int nbEntrees=0;

//ouverture du repertoire
dir = opendir(rep);

//si scandir echoue, message d'erreur et sortie
if (dir == NULL){
perror("opendir");
exit(1);
}

//on parcours toutes les entrees du repertoire
while((entree=readdir(dir))!=NULL){
//on ne traite pas . et ..
if((strcmp(entree->d_name,".")!=0)&&(strcmp(entree->d_name,"..")!=0)){

//on va creer la chaine de caractere "rep/nomEntree" pour les fichiers ou "rep/nomEntree/" pour les repertoires
nomTaille=strlen(rep)+strlen(entree->d_name);
//ligne * a ajouter

//stat rempli le buffer infosEntree avec les information concernant l'entree passe en 1er parametre
stat(entree->d_name,&infosEntree);

//si c'est un repertoire on incremente la taille de la chaine pour ajouter un separateur en fin de chaine
if(S_ISDIR(infosEntree.st_mode)) nomTaille++;

//allocation de memoire pour cette chaine !!!A EXTERNALISER!!!
nom=(char*)malloc(sizeof(char)*nomTaille+1); //+1 pour le separateur

//on concatene le nom du rep a la chaine, puis le separateur, puis le nom de l'entree, puis un dernier separateur s'il s'agit d'un sous rep
strcat(nom,rep);
strcat(nom,"/");
strcat(nom,entree->d_name);
if(S_ISDIR(infosEntree.st_mode)) strcat(nom,"/");

//S_ISDR prend en parametre le contenu de st_mode et renvoi 1 si l'entree est un repertoire, on verifie que l'entree est un repertoire et qu'il ne s'agit pas des repertoire "." ou ".."
if(S_ISDIR(infosEntree.st_mode)){
//on appel recursivement parcoursRep en passant en parametre ce nouveau repertoire rencontre
parcoursRep(entree->d_name);
}

//affichage du nom de l'entree
printf("%s\n", nom);
//on peut liberer l'espace reserve a cette entree
free (entree);
}
}


}

int main(int argc, char *argv[]){
parcoursRep(".");
}

19 réponses

Messages postés
3011
Date d'inscription
jeudi 26 septembre 2002
Statut
Membre
Dernière intervention
27 novembre 2004
8
popen("find ... "); tu pourra pas faire mieux

tu ve faire quoi en fait?
Messages postés
10
Date d'inscription
samedi 15 mai 2004
Statut
Membre
Dernière intervention
16 mai 2004

justement, c'est un projet qui consiste a reprogrammer la commande find...
ma 1ere etape c cet algo..
je l'ai modifier maintenant ca fonctionne presque...
seul le repertoire courant, lors du 1er appel, n'est pas traité..
Messages postés
3011
Date d'inscription
jeudi 26 septembre 2002
Statut
Membre
Dernière intervention
27 novembre 2004
8
c'est quoi ton algo en gros? (desolé mais c'est pas facile de lire le code comme ca)
Messages postés
10
Date d'inscription
samedi 15 mai 2004
Statut
Membre
Dernière intervention
16 mai 2004

il tourne sous linux donc j'utilise des appels systeme
tel que opendir (ouvrir rep), chdir (changer rep), stat (information sur le fichier)...

en gros l'algo prend le nom de rep passé en parametre
il parcours ses ficgiers et affichent leur nom complet (c'est a dire avec le chemin) et des qu'il tombe sur un dossier, il s'appel lui meme (c la que c recursif) etc...

le probleme c'est qu'il n'affiche pas le nom du rep courant seul
par ex dans l'arbroesence suivante :

rep0
--|---fich1
--|---rep1
--|-----|---rep2
--|-----|---fich2

il affichera :
rep0/fich1
rep0/rep1/rep2/
rep0/rep1/fich2
rep0/rep1/

mais il n'affichera pas
rep0/

je poste l'algo tt de suite :
Messages postés
10
Date d'inscription
samedi 15 mai 2004
Statut
Membre
Dernière intervention
16 mai 2004

#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include 

char *testArgChemin;  //si option name

//-- Fonction recursive qui Affiche le contenu du repertoire --//

void parcoursRep(char *rep, char *nomRepPere){

    //chaine de caractere a afficher pour chaque entree
    char *nom;

    //longueur de cette chaine
    int nomTaille;

    //flux repertoire
    DIR *dir;
    
    //une entree du repertoire 
    struct dirent *entree;

    //structure contenant les informations d'une entree
    struct stat infosEntree;

    //indice de defilement dans listeEntrees
    int n;

    //nombre d'entre du repertoire
    int nbEntrees=0;
   
    //ouverture du repertoire
    dir = opendir(rep);

    //si scandir echoue, message d'erreur et sortie
    if (dir == NULL){                              
      perror("opendir");
      exit(1);
    }

     chdir(rep);
    //on parcours toutes les entrees du repertoire
    while((entree=readdir(dir))!=NULL){        
        //on ne traite pas . et ..
        if((strcmp(entree->d_name,".")!=0)&&(strcmp(entree->d_name,"..")!=0)){
        
        //on va creer la chaine de caractere "rep/nomEntree" pour les fichiers ou "rep/nomEntree/" pour les repertoires
        nomTaille=strlen(nomRepPere)+strlen(entree->d_name);
        //ligne * a ajouter

        //stat rempli le buffer infosEntree avec les information concernant l'entree passe en 1er parametre
        stat(entree->d_name,&infosEntree);

        //si c'est un repertoire on incremente la taille de la chaine pour ajouter un separateur en fin de chaine
        if(S_ISDIR(infosEntree.st_mode)) nomTaille++;

        //allocation de memoire pour cette chaine !!!A EXTERNALISER!!!
        nom=(char*)malloc(sizeof(char)*nomTaille+2); //+1 pour le separateur +1 pour m \0

        //on concatene le nom du rep a la chaine, puis le separateur, puis le nom de l'entree, puis un dernier separateur s'il s'agit d'un sous rep
        strcat(nom,nomRepPere);
        //strcat(nom,"/");
        strcat(nom,entree->d_name);
        if(S_ISDIR(infosEntree.st_mode)) strcat(nom,"/");
       
        //S_ISDR prend en parametre le contenu de st_mode et renvoi 1 si l'entree est un repertoire, on verifie que l'entree est un repertoire et qu'il ne s'agit pas des repertoire "." ou ".."
        if(S_ISDIR(infosEntree.st_mode)){
          chdir(entree->d_name);
          //on appel recursivement parcoursRep en passant en parametre ce nouveau repertoire rencontre
          parcoursRep(".",nom);
          chdir("..");
        }
           
        //affichage du nom de l'entree
        //if(strcmp(entree->d_name,testArgChemin)==0){    //faire un si "crieterSatisait(name)
        printf("%s\n", nom);
        //}
        //on libere
        free(nom);
        //on peut liberer l'espace reserve a cette entree
        free (entree);
      } 
    }

}
                  
int main(int argc, char *argv[]){
   testArgChemin=(char*)malloc(sizeof(char)*4);
   strcat(testArgChemin,"iop");
   parcoursRep(".","./");
}

Messages postés
3011
Date d'inscription
jeudi 26 septembre 2002
Statut
Membre
Dernière intervention
27 novembre 2004
8
pour ton testArgChemin=(char*)malloc(sizeof(char)*4);

tu sais que tu peux tout simplement ecrire :
testArgChemin=malloc(4); :D la conversion void * => char * est plus qu'implicite

pour ton probleme de recursivite je sens le truc classique

imaginons cette arborescence

rep0
--|---fich1
--|---rep1
--|-----|---rep2
--|-----|---fich2
--|---fich2

fich2 est - il affiché ?
Messages postés
10
Date d'inscription
samedi 15 mai 2004
Statut
Membre
Dernière intervention
16 mai 2004

oui fich2 est affiché!
en fait dnas le code que j'ai posté y a des trucs en trop
pour plustard voici la version sans les trucs superflu

#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include 

//-- Fonction recursive qui Affiche le contenu du repertoire --//

void parcoursRep(char *rep, char *nomRepPere){

    //chaine de caractere a afficher pour chaque entree
    char *nom;

    //longueur de cette chaine
    int nomTaille;

    //flux repertoire
    DIR *dir;
    
    //une entree du repertoire 
    struct dirent *entree;

    //structure contenant les informations d'une entree
    struct stat infosEntree;

    //indice de defilement dans listeEntrees
    int n;

    //nombre d'entre du repertoire
    int nbEntrees=0;
   
    //ouverture du repertoire
    dir = opendir(rep);

    //si scandir echoue, message d'erreur et sortie
    if (dir == NULL){                              
      perror("opendir");
      exit(1);
    }

     chdir(rep);
    //on parcours toutes les entrees du repertoire
    while((entree=readdir(dir))!=NULL){        
        //on ne traite pas . et ..
        if((strcmp(entree->d_name,".")!=0)&&(strcmp(entree->d_name,"..")!=0)){
        
        //on va creer la chaine de caractere "rep/nomEntree" pour les fichiers ou "rep/nomEntree/" pour les repertoires
        nomTaille=strlen(nomRepPere)+strlen(entree->d_name);
        //ligne * a ajouter

        //stat rempli le buffer infosEntree avec les information concernant l'entree passe en 1er parametre
        stat(entree->d_name,&infosEntree);

        //si c'est un repertoire on incremente la taille de la chaine pour ajouter un separateur en fin de chaine
        if(S_ISDIR(infosEntree.st_mode)) nomTaille++;

        //allocation de memoire pour cette chaine !!!A EXTERNALISER!!!
        nom=(char*)malloc(sizeof(char)*nomTaille+2); //+1 pour le separateur +1 pour m \0

        //on concatene le nom du rep a la chaine, puis le separateur, puis le nom de l'entree, puis un dernier separateur s'il s'agit d'un sous rep
        strcat(nom,nomRepPere);
        //strcat(nom,"/");
        strcat(nom,entree->d_name);
        if(S_ISDIR(infosEntree.st_mode)) strcat(nom,"/");
       
        //S_ISDR prend en parametre le contenu de st_mode et renvoi 1 si l'entree est un repertoire, on verifie que l'entree est un repertoire et qu'il ne s'agit pas des repertoire "." ou ".."
        if(S_ISDIR(infosEntree.st_mode)){
          chdir(entree->d_name);
          //on appel recursivement parcoursRep en passant en parametre ce nouveau repertoire rencontre
          parcoursRep(".",nom);
          chdir("..");
        }
           
        //affichage du nom de l'entree
        printf("%s\n", nom);

        //on libere
        free(nom);
        //on peut liberer l'espace reserve a cette entree
        free (entree);
      } 
    }

}
                  
int main(int argc, char *argv[]){
   parcoursRep(".","./");
}
Messages postés
10
Date d'inscription
samedi 15 mai 2004
Statut
Membre
Dernière intervention
16 mai 2004

et si je le lance mon programme et que je compare son resultat
a celui de find bah j'ai une ligne en moins d'afficher..celle du 1 repertoire, celui ou je me trouve (ou celui passé en 1er argument
dans parcoursRep dans le main)

as-tu linux d'installé?
tui pourrais le compiler le tester par toi meme
Messages postés
3011
Date d'inscription
jeudi 26 septembre 2002
Statut
Membre
Dernière intervention
27 novembre 2004
8
je suis en train de tester, c'est quelques fonctions posix sont porté sous windows avec la distrib devcpp (et migwin)
Messages postés
10
Date d'inscription
samedi 15 mai 2004
Statut
Membre
Dernière intervention
16 mai 2004

okokok j'attds ton verdict
Messages postés
3011
Date d'inscription
jeudi 26 septembre 2002
Statut
Membre
Dernière intervention
27 novembre 2004
8
eu... je vois pas ou est le probleme, rep0 c'est le repertoire dans lequel tu te trouve, donc c'est la racine de l'arborescnce

faudrait etre audessu pour le voir, non?
Messages postés
3011
Date d'inscription
jeudi 26 septembre 2002
Statut
Membre
Dernière intervention
27 novembre 2004
8
quand tu fait un dind dans un repertoire rep par ex, est ce que il te sort aussi rep ?
Messages postés
3011
Date d'inscription
jeudi 26 septembre 2002
Statut
Membre
Dernière intervention
27 novembre 2004
8
si il te le sort, dans son traitement c'et forcement en dehors de l'algo recursif, fait pareil si tu ve, affiche le nom de ce repertoire
Messages postés
10
Date d'inscription
samedi 15 mai 2004
Statut
Membre
Dernière intervention
16 mai 2004

oui find me sort le rep,
il affiche "." c le rep courant...
Messages postés
3011
Date d'inscription
jeudi 26 septembre 2002
Statut
Membre
Dernière intervention
27 novembre 2004
8
tu pe faire pareil, mais en dehors de la recursivité, tu voi?
Messages postés
10
Date d'inscription
samedi 15 mai 2004
Statut
Membre
Dernière intervention
16 mai 2004

je vois ce que tu veux dire...
met en fait je crois que mon algo est faux..
j'ai tester avec d'autres chemins et ca me fait
des segmentation faute..

ca fait des 3 jours que je cherche un prog en C
de parcours recursif de repertoire et j'en trouve pas..
c dingue!!! pourtant ca doit pas etre dur a programmer..
Messages postés
3011
Date d'inscription
jeudi 26 septembre 2002
Statut
Membre
Dernière intervention
27 novembre 2004
8
ca segfault ? sur une grosse arborescence ? attend je vais essayer
Messages postés
3011
Date d'inscription
jeudi 26 septembre 2002
Statut
Membre
Dernière intervention
27 novembre 2004
8
oui, faut securiser tout ca

deja pour le nom te fait pas cher, c'est pas ca le but de l'allocation dynamique, on a des centaine de meg de plage virtuelle pourquoi tu te fait chier a economiser une poigne d'octet??

tu met au debut

char *nom=malloc(10000);

*nom=0; pour remettre une chaine vide

et free(nom); a la fin

en faisant ca ca plante beaucoup moin
Messages postés
3011
Date d'inscription
jeudi 26 septembre 2002
Statut
Membre
Dernière intervention
27 novembre 2004
8
en fait ca marche comme ca aparament