Обход каталогов в C

Я пытался найти этот вопрос, но не смог найти удовлетворительного ответа. Итак, вот мой вопрос:

Я перебираю каталоги со следующими вариантами кода:

Я.

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

void traverseDirectory(char name[100]){
        DIR* dir;
        struct dirent *ent;
        struct stat states;

        dir = opendir(name);

        while((ent=readdir(dir)) != NULL){
                stat(ent->d_name,&states);
                if(!strcmp(".", ent->d_name) || !strcmp("..", ent->d_name)){
                        continue;
                }
                else{
                        printf("%s/%s\n",name,ent->d_name);
                        if(S_ISDIR(states.st_mode)){
                                strcat(name,"/");
                                strcat(name,ent->d_name);
                                traverseDirectory(name);
                        }
                }
        }

        closedir(dir);
}

int main(){
        char path[100];
        printf("Enter the path:\n");
        scanf("%s",&path);
        traverseDirectory(path);
}

Он проходит через подкаталоги, но дает ошибку сегментации после прохождения через первый подкаталог и печати его файлов.

Выход:

Enter the path:
/home/harshad/dump

/home/harshad/dump/TraverseDirectory.c

/home/harshad/dump/temp

/home/harshad/dump/temp/temptest.txt
Segmentation fault

II.

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

void traverseDirectory(char name[100]){
        DIR* dir;
        struct dirent *ent;
        struct stat states;

        dir = opendir(name);

        while((ent=readdir(dir)) != NULL){
                stat(ent->d_name,&states);
                if(!strcmp(".", ent->d_name) || !strcmp("..", ent->d_name)){
                        continue;
                }
                else{
                        printf("%s/%s\n",name,ent->d_name);
                        if(S_ISDIR(ent->d_type & DT_DIR)){
                                strcat(name,"/");
                                strcat(name,ent->d_name);
                                traverseDirectory(name);
                        }
                }
        }

        closedir(dir);
}

int main(){
        char path[100];
        printf("Enter the path:\n");
        scanf("%s",&path);
        traverseDirectory(path);
}

Он печатает все файлы и подкаталоги в данном каталоге, но не перемещается в подкаталогах. Это вывод:

Enter the path:
/home/harshad/dump

/home/harshad/dump/TraverseDirectory.c

/home/harshad/dump/temp

/home/harshad/dump/TraverseDirectory1.out

/home/harshad/dump/dump

/home/harshad/dump/test.txt

/home/harshad/dump/SortMarks.c

/home/harshad/dump/TraverseDirectory.out

/home/harshad/dump/TraverseDirectoryTemp.out

/home/harshad/dump/TraverseDirectory1.c

/home/harshad/dump/TraverseDirectoryTemp.c

/home/harshad/dump/FindEven.c

Здесь dump & temp - это подкаталоги, каждый из которых содержит несколько файлов. Сначала я подумал, что из-за разрешений пользователей он может не проходить в подкаталогах (так как они созданы и принадлежат пользователю root), но, как вы можете видеть из результатов 1-й программы, это не так. Поэтому я не могу понять проблемы с обеими программами. PS: в выходных данных после первых двух строк программа печатает каталоги и файлы.

2 ответа

Решение

Вы должны действительно проверить на наличие ошибок в opendir(), Если это не удастся, он вернется NULLи затем следующий readdir() будет сег-вина.

Этого может быть достаточно:

dir = opendir(name);
if (!dir)
{
    perror(name);
    return;
}

Вы объединяете каждое имя файла с именем, переданным с этим:

strcat(name,ent->d_name);

но не отменяя это готово к следующему файлу. Таким образом, строка становится все длиннее и длиннее, пока не нарушит свой выделенный размер.

Вы должны создать другую строку локально, чтобы сохранить переданное имя.

char localname[100];
strcpy(localname, name);
strcat(localname,"/");
strcat(localname,ent->d_name);
traverseDirectory(localname);

но с лучшей защитой от ошибок, чем я использовал.

Другие вопросы по тегам