Проблема чтения каталогов в C - PullRequest
2 голосов
/ 20 сентября 2011

Я пишу простую программу на C, которая получает каталог в качестве аргумента и отображает файлы в этом каталоге, а также его подкаталоги. Я написал «рекурсивную» функцию для этого. Но по неизвестной причине моя программа не работает с функцией stat. Вот моя программа:

    #define _POSIX_SOURCE 1

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


void display_directory(char* path){

  DIR* directory = opendir(path);
  if( directory == NULL){
    printf("opendir failure for %s\n", path);
    exit(1);
  }


 struct dirent* dirent;
 struct stat stat_info;

 while((dirent = readdir(directory)) != NULL){
   printf("[%s]\n", dirent->d_name);
   if(stat(dirent -> d_name, &stat_info) == -1){
     printf("readdir error for %s\n", dirent->d_name);
     exit(1);
   }
   if(S_ISREG(stat_info.st_mode)){
       printf("File: %s \n", dirent -> d_name); 
   }
   if(S_ISDIR(stat_info.st_mode)){
     if(strncmp(dirent->d_name, "..",2)){
       printf("Directory : %s\n", dirent->d_name);
       display_directory(dirent->d_name);
     }  
    }

 }

 closedir(directory);
}

int main(int argc, char* argv[]){

char* path;

if(argc > 1){
 path = argv[1];
} else {
 path = ".";
}

display_directory(path);

 return EXIT_SUCCESS;
}

Например, если в моем каталоге A у меня есть a1, a2, a3 и .., он сначала читает каталог .., а когда он читает каталог a1, функция stat завершается ошибкой.

Может кто-нибудь подскажет, что не так с моим кодом.

[EDIT] Я включил <errno.h>, как многие из вас предлагают, и после запуска программы у меня появляется ошибка Too many open files.

    #define _POSIX_SOURCE 1

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


void display_directory(char* path){

  DIR* directory = opendir(path);
  if( directory == NULL){
    printf("opendir failure for %s --> %s\n", path, strerror(errno));
    exit(1);
  }


 struct dirent* dirent;
 struct stat stat_info;

 while((dirent = readdir(directory)) != NULL){
   printf("[%s]\n", dirent->d_name);
   if(stat(dirent->d_name, &stat_info)){
     printf("readdir error for %s ---> %s\n", dirent->d_name, strerror(errno));
     continue;
   }
   if(S_ISREG(stat_info.st_mode)){
       printf("Fichier : %s \n", dirent->d_name); 
   }
   if(S_ISDIR(stat_info.st_mode)){
     if(strncmp(dirent->d_name, "..",2)){
       printf("Directory : %s\n", dirent->d_name);
       display_directory(dirent->d_name);
     }  
    }

 }

 closedir(directory);
}

int main(int argc, char* argv[]){

char* path;

if (argc > 2) { 
 fprintf(stderr, "Usage: %s [directory]\n", argv[0]); 
 exit(1); 
}

path = argv[1];


display_directory(path);

 return EXIT_SUCCESS;
}

Вывод программы:

[..]
[mykill.c]
readdir error for mykill.c ---> No such file or directory
[.]
Directory : .
[..]
[.]
Directory : .
[..]
[.]
Directory : .
[..]

...
...
Directory : .
opendir failure for . --> Too many open files

mykill.c - это файл в каталоге, который был передан в качестве аргумента.

Ответы [ 4 ]

5 голосов
/ 20 сентября 2011

У меня довольно хорошая идея, что не так, но я хочу рассказать вам, как сначала отладить это для себя. Изменить этот код ...

if(stat(dirent -> d_name, &stat_info) == -1){
  printf("readdir error for %s\n", dirent->d_name);
  exit(1);
}

... читать вместо ...

if (stat(dirent->d_name, &stat_info)) {
    printf("%s: %s\n", dirent->d_name, strerror(errno));
    continue;
}

Вам нужно будет добавить в список включения

#include <errno.h>

Запустите программу еще раз. Если вы не видите в выходных данных, в чем проблема, то отредактируйте выходные данные ЗАВЕРШЕНО, НЕ УДАЛЕНО в свой вопрос, и мы пойдем оттуда.

1 голос
/ 16 сентября 2013

Вы делаете статист только с именем файла (без полного пути), добавляете полный путь к имени файла или меняете рабочий каталог перед вызовом статистики.

1 голос
/ 20 сентября 2011
if(S_ISDIR(stat_info.st_mode)){
 if( !strcmp(dirent->d_name, ".")) continue;
 if( !strcmp(dirent->d_name, "..")) continue;

 printf("Directory : %s\n", dirent->d_name);
 display_directory(dirent->d_name);
}
0 голосов
/ 20 сентября 2011

Использование nftw().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...