1

I want to know how ls -R implemented in C language. Is it use the recursion algorithm?

4
  • 1
    What is the actual problem you are trying to solve? Commented Oct 22, 2012 at 6:39
  • 1
    I'm afraid recursion brings about stack overflow. Commented Oct 22, 2012 at 6:43
  • Recursing in your case might cause stack - overflow, if you do not skip the directories . and .. Commented Oct 22, 2012 at 6:48
  • There is no single recursion algorithm. But some algorithms (actually, set of functions) may be [co-]*recursive* and recursion is a feature of such algorithms. Commented Oct 22, 2012 at 7:21

5 Answers 5

2

"ls" (at least the implementations that I know of) use fts_open, fts_read ... to traverse a file hierarchy. These are "non-recursive" methods which maintain a list of the visited directories internally.

Use "man fts_read" or http://linux.die.net/man/3/fts_read to get more information about these functions.

Sign up to request clarification or add additional context in comments.

Comments

2

Just for completeness, ls is part of GNU coreutils: www.gnu.org/software/coreutils/.

Comments

2

Here's the relevant code-block

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

Later, the directory listing is done recursively because of the above int flag.

See source here.

Recursing in your case might cause stackoverflow, if you do not skip the directories . and ...

It doesn't seem like any recursion is done within ls.c though. It uses fts-functions, like fts_children to traverse the heirarchies. You could use the same.

4 Comments

The variable is called f_recursive, but the implementation is not recursive: the traverse() function (from the linked source) does not call itself recursively.
@MartinR I hadn't looked in detail. Will update answer. Thanks.
@MartinR, fts_children seems to do all the work, fetching the listing, so I guess there isn't any recursion within ls.c but within, fts, there is.
I am quite sure that fts does not use recursion internally, but I had written that already in my answer.
2

This is a simple linux ls -R implementation in C. It gives coloured output similar to 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;
}

Comments

1

I think this would help you.

 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);
  }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.