Unix c программа для рекурсивного вывода списка каталогов - PullRequest
3 голосов
/ 12 августа 2011

Я работаю над учебным упражнением POSIX 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;
}

Ответы [ 3 ]

5 голосов
/ 12 августа 2011

Элемент d_name в struct dirent является базовым именем рассматриваемого элемента. Итак, если вы просматриваете каталог, подобный этому:

.
..
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 голосов
/ 01 июня 2013

Вы должны использовать ftw для этого, он вызывает определенный обратный вызов для каждого элемента поддерева.Таким образом, вы избегаете использования явной рекурсии самостоятельно, и ваш код станет намного короче.

2 голосов
/ 12 августа 2011

Включение предупреждений покажет, что вы передаете неправильный тип при выполнении рекурсивного вызова функции.Я просто заставил бы listdir принимать аргумент char * вместо char **, а затем использовать цикл for в main для циклического перебора нескольких аргументов, если вам нужно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...