Trying to emulate recursive ls command(very new to c)

  • Thread starter Thread starter FYAD
  • Start date Start date
Click For Summary

Discussion Overview

The discussion revolves around a user's attempt to create a C program that recursively lists files and directories, similar to the 'ls' command in Unix-like systems. Participants provide feedback on the user's code, suggest improvements, and discuss potential issues related to recursion and directory handling.

Discussion Character

  • Exploratory
  • Technical explanation
  • Debate/contested
  • Mathematical reasoning

Main Points Raised

  • The user reports successfully listing files in the current directory but encounters a segmentation fault when attempting to access subdirectories.
  • Some participants suggest that using global variables, such as 'dp', in recursive functions can lead to issues, and recommend making 'dp' a local variable instead.
  • One participant humorously suggests using the system command 'ls -R' as a simpler alternative, prompting a discussion about whether this approach would truly emulate the functionality of the user's program.
  • Another participant points out that the user should check the logic in their code, particularly around the use of 'readdir' and the handling of directory entries.
  • Suggestions are made to restructure the 'listit' function to use loops for processing files and directories separately, which may help clarify the flow of the program.
  • A participant mentions the need to change the working directory using 'chdir' when entering a new directory, which could be a necessary step in the user's implementation.

Areas of Agreement / Disagreement

Participants express differing views on the best approach to resolve the user's issues, with no consensus on a single solution. Various strategies are proposed, indicating multiple competing views on how to effectively implement the recursive listing of directories.

Contextual Notes

Limitations in the user's understanding of directory handling and recursion are evident, as they express confusion about the flow of their program. There are also unresolved issues regarding the handling of directory entries and the use of parameters in the 'listit' function.

Who May Find This Useful

Individuals interested in C programming, particularly those learning about file handling, recursion, and directory traversal, may find this discussion beneficial.

FYAD
Messages
5
Reaction score
0
I'm very new to programming in c, and I'm trying to write a program that recursivley lists all the files in a directory, as well as all of the subdirectores and their files. I'm having some problems.

On my first go I was able to get all of the files of the current directory to be listed. That was easy. I'm having trouble getting my program to jump into all of the subdirectories and then get back to the original directory and list its files. My code seems to jump into the first subdirectory and list its files, but it ends with a Segmentation fault. I googled the error and found out what it means, but I have no idea how to go about remedying it.


Code:
#include <stdio.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/times.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <limits.h>
#include <dirent.h>
#include <unistd.h>


int x = 0;
struct dirent *dp;

void listit(DIR *dirp,DIR *tdirp,int level){
  errno = 0;
  if (!(dp = readdir(dirp))) {
    if (errno == 0) {
      printf("porblem\n");
    } 
    else {
      printf("Error reading entry in directory\n");
      return;
    } 
  } 
  else {
    tdirp = (opendir(dp->d_name));
    if(tdirp){
      if(!((strcmp(dp->d_name,".")) == 0 || strcmp(dp->d_name,"..") == 0)){
	printf("-----------NEW DIRECTORY--------------\n");
	printf(" %s\n",dp-> d_name);
	dirp = opendir(dp->d_name);
	listit(dirp,tdirp,level);
       }
       else{
	 printf("%s\n",dp->d_name);
	 listit(dirp,tdirp,level);
       }
    }
    printf("%s\n",dp->d_name);
    listit(dirp,tdirp,level);
  }
}
   


int main(int argc, char *argv[]){
   struct timeval t;
   int i, status = 0;
   int count = 0;
   int level = 0;
   DIR *dirp;
   DIR *tdirp;
   dirp = opendir(argv[1]);
   
   if (argc < 2) { exit(-1); }

 if ((status = gettimeofday(&t,0)) != 0) {
      printf("Error - time call failed\n");
   }
      
   if (!dirp) {
      if (access(argv[1],F_OK)) {
         printf("Error - couldn't interpret %s as directory.\n", argv[1]);
         printf("----------------------------------\n\n");
      }
      else {
         printf("%s\n", argv[1]);
         printf("----------------------------------\n\n");
      }
   }
   else {
      printf("Contents of directory %s:\n", argv[1]);
       listit(dirp,tdirp,level);     

   }
}
 
Technology news on Phys.org
The c compiler is complaining because there is a 'porblem' in your code. (Just kidding.)

I don't see anything particularly obvious. I'm guessing that dp gets clobbered somwhere. Are you sure it should be global?
 
Nate's got it. It's a very bad idea for a recursive function to use globals, by the way.

- Warren
 
If you can include stdlib.h then you can simply do this:

system("ls -R")
 
dduardo said:
If you can include stdlib.h then you can simply do this:

system("ls -R")

That wouldn't exactly be emulating ls now, would it?
 
I changed dp to a local and passed it into listit. Directores still aren't getting read though?

Maybe my understanding of what's going on is incorrect.

In my main method I have dirp = opendir(argv[1]);, which reads in a directory name from the command line and attempts to open the directory.

If dirp is a valid directory name, it opens the directory and then passes the name up to function listit.

In listit, it checks to see if there are files in the directory ( the line if (!(dp = readdir(dirp))) { ), if so, it goes to the else where tdirp reads in the first file in the directory and checks if it is a sub-directory.

If it is a directory, it checks to see if the directory is "." or "..". If it is not, it prints the directory name and opens it, followed by a recursive call to listit. So, listit gets called with the new directory name and the whole thing starts over.

If it's "." or "..", it calls listit again. dp is set to the next file in the directory and it starts again.

If it's not a directory, it's a file, and the file name is printed. listit is called and the whole thing starts over.

Except new directories are never entered. gah!
 
Hi:
if (!(dp = readdir(dirp)))

shouldn't this be:
if (!(dp == readdir(dirp)))?
 
You might consider using a loop in listit() to process each "current" directory, then recursively calling listit() for each sub-directory encountered. You already mentioned changing dp to be a local variable. I don't understand why you pass dirp or tdirp or level as parameters, as dirp also needs to be a local variable. The only thing you need to pass to listit() is the name string for the directory. Then the local copy of dirp gets the result from doing an opendir(...name...).

Another alternative is to have two loops in listit(). The first loop processes all files, the second loop processes all directories (via recursive calls). This keeps all the files in a directory adjacent to each other the list.
 
  • #10
If you didn't find the solution yet.
when you find new directory you have to call.

chdir(dir); in order to enter il.
 

Similar threads

Replies
8
Views
5K
  • · Replies 75 ·
3
Replies
75
Views
7K
  • · Replies 4 ·
Replies
4
Views
2K
  • · Replies 4 ·
Replies
4
Views
2K
  • · Replies 5 ·
Replies
5
Views
2K
  • · Replies 2 ·
Replies
2
Views
3K
  • · Replies 3 ·
Replies
3
Views
2K
Replies
3
Views
3K
Replies
1
Views
2K
  • · Replies 5 ·
Replies
5
Views
4K