2017-03-27 4 views
1

디렉터리의 모든 폴더와 파일을 파일 크기와 함께 재귀 적으로 나열하는 프로그램을 작성하려고합니다. 프로그램이 하위 폴더의 한 수준 만 깊이 보이기 때문에 저는 첫 번째 부분을 계속 작업하고 있습니다.하위 폴더를 재귀 적으로 방문 할 수 없습니다.

누구든지 여기에서 문제를 파악할 수 있습니까? 나는 붙어있다.

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

void listdir(const char *name) { 
    DIR *dir; 
    struct dirent *entry; 
    int file_size; 

    if (!(dir = opendir(name))) 
     return; 
    if (!(entry = readdir(dir))) 
     return; 

    do { 
     if (entry->d_type == DT_DIR) { 
      char path[1024]; 
      if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) 
       continue; 
      printf("./%s\n", entry->d_name); 
      listdir(entry->d_name); 
     } 
     else 
      printf("./%s\n", entry->d_name); 
    } while (readdir(dir) != NULL); 
    closedir(dir); 
} 

int main(void) 
{ 
    listdir("."); 
    return 0; 
} 
+2

[GCC] (http://gcc.gnu.org/)를 사용하는 경우 모든 경고 및 디버그 정보 ('gcc -Wall -g')로 컴파일하십시오. ** 디버거 ** ('gdb')를 사용하십시오. fix-my-code 질문은 주제와 관련이 없으며 표준 C는 디렉토리에 대해 알지 못하기 때문에 (* POSIX는 그렇지만) * linux * 또는 * POSIX *와 같은 다른 태그가 없습니다. –

+2

단순히 반환하는 대신 오류를보고하는 것은 좋은 생각 일 수 있습니다 ... – Olaf

+0

'char * path [1024]'는 여러분이 원하는 것이 아닌'char' 포인터의 배열을 할당합니다 ... – bejado

답변

3

첫 번째 문제는 당신이 readdir의 반환 값을 포기하는, 그동안의 상태에, 그것은 항목에 할당해야합니다.

또한 listdir을 재귀 호출 할 때는 경로 앞에 부모 이름을 추가해야하며, 그렇지 않으면 항상 현재 작업 디렉토리에서 검색합니다.

void listdir(const char *name) { 
    DIR *dir; 
    struct dirent *entry; 
    int file_size; 

    if (!(dir = opendir(name))) 
      return; 

    while ((entry = readdir(dir)) != NULL) { // <--- setting entry 
      printf("%s/%s\n", name, entry->d_name); 
      if (entry->d_type == DT_DIR) { 
        char path[1024]; 
        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) 
          continue; 
        sprintf(path, "%s/%s", name, entry->d_name); // <--- update dir name properly by prepend the parent folder. 
        listdir(path); 
      } 
    } 
    closedir(dir); 
} 

int main(void) 
{ 
    listdir("."); 
    return 0; 
} 
+1

조기에 오픈 디렉토리 디스크립터가 누설됩니다. 그 좋지 않다. 'do {...} while' 루프는 질문과 답변에서 모두 부적절합니다. –

+0

맞습니다. 반환 전에 문을 닫아야합니다. 루프가 더 좋을 수도 있습니다. – fluter

2

다음은 코드에 대한 최소 수정 사항입니다. 나는 비표준 인 asprintf을 자유롭게 사용했다. glibc를 사용하지 않는 경우 snprintf 또는 그 대신에 사용해야합니다.

가장 중요한 것은 listdir에 주어진 경로는 현재 작업 디렉토리의 완전한 상대 경로 여야합니다. 또는 절대 경로. 그러나 entry->d_name의 파일 이름은 파일의 기본 이름입니다. 따라서 그것은 listdir에 전달 된 경로와 연결되어야합니다. 부적절한 것을 do ... whilewhile 루프로 변경했습니다.

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

void listdir(const char *path) { 
    DIR *dir; 
    struct dirent *entry; 

    if (!(dir = opendir(path))) 
     return; 

    while ((entry = readdir(dir))) { 
     if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) 
      continue; 

     char *current; 
     if (asprintf(&current, "%s/%s", path, entry->d_name) < 0) { 
      // asprintf failed 
      fprintf(stderr, "asprintf failed, exiting"); 
      goto exit; 
     } 

     puts(current); 
     if (entry->d_type == DT_DIR) { 
      listdir(current); 
     } 

     free(current); 
    } 

exit: 
    closedir(dir); 
} 

int main(void) 
{ 
    listdir("."); 
}