2012-10-22 107 views
1

我想知道ls -R如何在C語言中實現。 它使用遞歸算法嗎?在linux中實現ls -R命令

+1

什麼是你正在試圖解決實際問題的輸出? –

+1

恐怕遞歸會導致堆棧溢出。 – chyanog

+0

如果您不跳過目錄'.'和'..',則在您的情況下進行遞歸可能會導致堆棧溢出。 –

回答

2

「LS」(至少我所知道的實現)使用fts_openfts_read ......遍歷文件層次。這些是「非遞歸」方法,它們在內部維護訪問目錄的列表。

使用「man fts_read」或http://linux.die.net/man/3/fts_read可獲得有關這些功能的更多信息。

2

下面是相關的代碼塊

<includes...> 
int f_recursive;  /* ls subdirectories also */ 
while ((ch = getopt(argc, argv, "1ABCFLRSTWabcdfghiklmnopqrstuwx")) != -1) { 
    switch (ch) { 
. 
. 
. 
. 
case 'R': 
    f_recursive = 1; 
    break; 

後來,目錄列表,因爲上述INT標誌完成遞歸。

See source here.

遞歸,你的情況可能會導致計算器,如果不要跳過目錄...

雖然在ls.c內似乎沒有任何遞歸。它使用fts-functions,像fts_children來遍歷heirarchies。你可以使用相同的。

+0

該變量稱爲'f_recursive',但實現不是遞歸的:'traverse()'函數(來自鏈接源)不會遞歸調用它自己。 –

+0

@MartinR我沒有看詳細。將更新答案。謝謝。 –

+0

@MartinR,[fts_children](http://www.kernel.org/doc/man-pages/online/pages/man3/fts.3.html)似乎做了所有的工作,取得上市,所以我猜在'ls.c'中沒有任何遞歸,但是在內部有fts。 –

2

爲了完整起見,ls是GNU coreutils的一部分:www.gnu.org/software/coreutils/。

1

我認爲這對你有幫助。

void listDir(char *dirName) 
{ 
    DIR* dir; 
    struct dirent *dirEntry; 
    struct stat inode; 
    char name[1000]; 
    dir = opendir(dirName); 
    if (dir == 0) { 
     perror ("Eroare deschidere fisier"); 
     exit(1); 
    } 
    while ((dirEntry=readdir(dir)) != 0) { 
     sprintf(name,"%s/%s",dirName,dirEntry->d_name); 
     lstat (name, &inode); 

     // test the type of file 
     if (S_ISDIR(inode.st_mode)) 
      printf("dir "); 
     else if (S_ISREG(inode.st_mode)) 
      printf ("fis "); 
     else 
      if (S_ISLNK(inode.st_mode)) 
      printf ("lnk "); 
     else; 
      printf(" %s\n", dirEntry->d_name); 
    } 
2

這是在C的簡單的Linux ls -R實現它給有色類似ls

#include <stdio.h> 
#include <dirent.h> 
#include <string.h> 
#define GREEN "\x1b[32m" 
#define BLUE "\x1b[34m" 
#define WHITE "\x1b[37m" 

void Usage() { 
    fprintf(stderr, "\nUsage: exec [OPTION]... [DIR]...\n"); 
    fprintf(stderr, "List DIR's (directory) contents\n"); 
    fprintf(stderr, "\nOptions\n-R\tlist subdirectories recursively\n"); 
    return; 
} 

void RecDir(char *path, int flag) { 
    DIR *dp = opendir(path); 
    if(!dp) { 
     perror(path); 
     return; 
    } 
    struct dirent *ep; 
    char newdir[512]; 
    printf(BLUE "\n%s :\n" WHITE, path); 
    while((ep = readdir(dp))) 
     if(strncmp(ep->d_name, ".", 1)) 
      printf(GREEN "\t%s\n" WHITE, ep->d_name); 
    closedir(dp); 
    dp = opendir(path); 
    while((ep = readdir(dp))) if(strncmp(ep->d_name, ".", 1)) { 
     if(flag && ep->d_type == 4) { 
      sprintf(newdir, "%s/%s", path, ep->d_name); 
      RecDir(newdir, 1); 
     } 
    } 
    closedir(dp); 
} 

int main(int argc, char **argv) 
{ 
    switch(argc) { 
    case 2: 
     if(strcmp(argv[1], "-R") == 0) Usage(); 
     else RecDir(argv[1], 0); 
     break; 
    case 3: 
     if(strcmp(argv[1], "-R") == 0) RecDir(argv[2], 1); 
     else Usage(); 
     break; 
    default: Usage(); 
    } 
    return 0; 
}