I am working on a POSIX C learning exercise that involves recursively listing files/folders in a specified directory. The program takes in as arguments of one or more directories. I can list the contents of the initial directory fine but having a problem with the recursion. Is something wrong with the way I am passing in the argument for the recursive function call?
#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(myd开发者_运维问答irent->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;
}
The d_name
member of struct dirent
is the basename of the item in question. So, if you're going through a directory like this:
.
..
where-is/
pancakes/
.
..
house
Once you're in where-is
, you'll try to listdir("pancakes")
but that won't work because you need to listdir("where-is/pancakes")
.
You need to combine that with the name of the directory that you're looking before you have something that you can pass to the next listdir
call.
You'll want to replace things like this:
listdir(mydirent->d_name);
with things like this:
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);
Alternatively, you could chdir
into the directories as you enter them and then chdir
back up when you're done.
Turning on warnings will show that you're passing the wrong type when making the recursive function call. I would simply make listdir
take a char *
argument rather than char **
, and then use a for loop in main
to loop over multiple arguments if you need to.
You should use ftw
for this, it calls a given callback on every item of the subtree. This way, you avoid using explicit recursion yourself, and your code will get much shorter.
精彩评论