2011-08-12 88 views
2

我正在研究POSIX C學習練習,它涉及遞歸列出指定目錄中的文件/文件夾。該程序接受一個或多個目錄的參數。我可以列出初始目錄的內容,但是遞歸存在問題。我在遞歸函數調用的參數中傳遞的方式有問題嗎?Unix c程序遞歸列出目錄

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

void listdir(char *argv[]) 
{ 
    DIR *mydirhandle; 

    struct dirent *mydirent; 

    struct stat statinfo; 

    int n = 1; 

    while(argv[n] != NULL) 
    { 
    if((mydirhandle = opendir(argv[n])) == NULL) 
    { 
     perror("opendir"); 
     exit(1); 
    } 

    printf("%s/\n", argv[n]); 

    while((mydirent = readdir(mydirhandle)) != NULL) 
    { 
     if((strcmp(mydirent->d_name, ".") == 0) || (strcmp(mydirent->d_name, "..") == 0)) 

     { 
     continue; 
     } 

     else   
     { 
     printf("\t%s\n", mydirent->d_name); 

     //check if next entry is a directory  
     if(mydirent->d_type == DT_DIR) 
     { 
      //is current directory being passed correctly here? 
      listdir(mydirent->d_name); 
     } 
     }   
    }      
    n++; 
    closedir(mydirhandle); 
    } 
} 
int main(int argc, char *argv[]) 
{ 
    if(argc < 2) 
    { 
    printf("usage: %s <directory>\n", argv[0]); 
    return 0; 
    } 

    listdir(argv); 
    return 0; 
} 

回答

2

打開警告將顯示您在進行遞歸函數調用時傳遞錯誤的類型。我只需簡單地使listdir採用char *參數而不是char **,然後在main中使用for循環來循環多個參數(如果需要的話)。

5

struct dirent的的d_name構件是有問題的項目的基本名稱。所以,如果你正在經歷一個目錄是這樣的:

. 
.. 
where-is/ 
    pancakes/ 
     . 
     .. 
     house 

一旦你where-is的時候,你會嘗試listdir("pancakes")但不會工作,因爲你需要listdir("where-is/pancakes")

您需要將它與您正在查找的目錄名稱結合起來,然後才能將其傳遞給下一個listdir調用。

你要替換類似這樣的事情:

listdir(mydirent->d_name); 

有這樣的事情:

char *next_dir = malloc(strlen(argv[n]) + strlen(mydirent->d_name) + 1 + 1); 
sprintf(next_dir, "%s/%s", argv[n], mydirent->d_name); 
listdir(next_dir); 
free(next_dir); 

或者,你可以chdir到目錄中,當你進入他們,然後chdir備份當你完成。

2

您應該使用ftw爲此,它調用子樹的每個項目上的給定回調。這樣,你可以避免自己使用明確的遞歸,並且你的代碼會變得更短。