以递归方式搜索目录中的C中的最大文件

时间:2015-02-04 04:45:15

标签: c file recursion structure ls

此程序的目标是获取目录的命令行参数,并打印该目录下的前10个最大文件(包括子目录)。到目前为止,我只是试图让它以递归方式打印文件及其大小。我使用一个结构来包含文件名及其大小,并将这些结构存储在一个数组中。但由于某种原因,程序似乎没有将子目录文件的信息添加到数组中。排序似乎也是关闭的,但我认为这是同一问题的一部分,因为它为num_entries返回错误的值,因为它没有正确地记录所有文件。我确定这是递归逻辑中的某种缺陷,但我似乎无法找到它。如果有人可以向我提供正确方向的任何指示(ha),我将不胜感激。谢谢!

(这也是我在这里发表的第一篇文章,所以如果还有其他任何我做错了,格式化我的帖子也让我知道。)

#include <unistd.h>
#include <sys/types.h>
#include <dirent.h>
#include <stdio.h>
#include <sys/stat.h>
#include <string.h>
#include <stdlib.h>

#define K   1024
#define CHUNK   16

typedef struct mls { 
    char *ml_name;
    long ml_size;
} ML_ENTRY;

ML_ENTRY **getentries (int *num_entries, const char *name, int level);
void swap(ML_ENTRY *list[], int pos1, int pos2);
void quicksort(ML_ENTRY *list[], int n);

ML_ENTRY **getentries (int *num_entries, const char *name, int level)
{
  DIR *dir;
  struct dirent *entry;
  struct stat st;
  int rv;
  int n;
  int size;
  char path[K];
  ML_ENTRY **li;

  if (!(dir = opendir (name)))
    return;
  if (!(entry = readdir (dir)))
    return;

  size = CHUNK;
  n = 0;
  li = malloc(size * sizeof(ML_ENTRY *));

  while (entry = readdir (dir)){
          if(n >= size){
          size <<= 1;
          li = realloc(li, size*sizeof(ML_ENTRY));
      }
      int len =
        snprintf (path, sizeof (path) - 1, "%s/%s", name, entry->d_name);
      rv = lstat(path, &st);
      if (entry->d_type == DT_DIR){
      path[len] = 0;
      if (strcmp (entry->d_name, ".") == 0
          || strcmp (entry->d_name, "..") == 0)
        continue;
      getentries(num_entries, path, level + 1);
    }
    if (rv < 0)
        continue;
    li[n] = malloc(sizeof(ML_ENTRY));
    li[n]->ml_name = strdup(entry->d_name);
    li[n++]->ml_size = st.st_size;
    }
  closedir (dir);
  *num_entries = n;
  return li;
}


int main (int argc, char *argv[])
{
  int nentries;
  ML_ENTRY **list;
  char dir[K];
  int i;

  if (argc > 1)
    strcpy(dir, argv[1]);
  else  
      strcpy(dir, ".");

  list = malloc(sizeof(ML_ENTRY*));

  list = getentries(&nentries, dir, 0);
  quicksort(list, nentries);

  for(i = 0; i < nentries; i++)
      printf("%5d %s\n", list[i]->ml_size, list[i]->ml_name);

  return 0;
}

void swap(ML_ENTRY *list[], int pos1, int pos2)
{
  ML_ENTRY *tmp;

  tmp = list[pos1];
  list[pos1] = list[pos2];
  list[pos2] = tmp;
}
void quicksort(ML_ENTRY *list[], int n)
{
  int last;
  int i;

  if(n < 2)
    return;
  last = 0;
  for(i=1;i<n;i++)
    if(list[i]->ml_size > list[0]->ml_size)
      swap(list, ++last, i);
  swap(list, 0, last);
  quicksort(list, last - 1);
  quicksort(list + last + 1, n - last - 1);
}



void swap(ML_ENTRY *list[], int pos1, int pos2)
{
  ML_ENTRY *tmp;

  tmp = list[pos1];
  list[pos1] = list[pos2];
  list[pos2] = tmp;
}
void quicksort(ML_ENTRY *list[], int n)
{
  int last;
  int i;

  if(n < 2)
    return;
  last = 0;
  for(i=1;i<n;i++)
    if(list[i]->ml_size > list[0]->ml_size)
      swap(list, ++last, i);
  swap(list, 0, last);
  quicksort(list, last - 1);
  quicksort(list + last + 1, n - last - 1);
}

1 个答案:

答案 0 :(得分:1)

你说,

  

出于某种原因,程序似乎没有将子目录文件的信息添加到数组中。

在函数getentries中,您有一个递归调用来处理子目录:

     getentries(num_entries, path, level + 1);

正在忽略来自该递归调用的返回值。这就是为什么你没有看到输出中与子目录相对应的任何条目。

<强>更新

这是更新的函数,用于处理子目录的条目。

ML_ENTRY **getentries (int *num_entries, const char *name, int level)
{
   DIR *dir;
   struct dirent *entry;
   struct stat st;
   int rv;
   int n;
   int size;
   char path[K];
   ML_ENTRY **li;

   // Add variables to deal with the entries from sub-directories.
   ML_ENTRY **subDirectoryLi;
   int subDirctoryNumEntries;
   int i;

   if (!(dir = opendir (name)))
      return;

   size = CHUNK;
   n = 0;
   li = malloc(size * sizeof(ML_ENTRY *));

   while (entry = readdir (dir)){
      if(n >= size){
         size <<= 1;
         li = realloc(li, size*sizeof(ML_ENTRY*));
      }
      int len =
         snprintf (path, sizeof (path) - 1, "%s/%s", name, entry->d_name);
      rv = lstat(path, &st);
      if (entry->d_type == DT_DIR){
         path[len] = 0;
         if (strcmp (entry->d_name, ".") == 0
             || strcmp (entry->d_name, "..") == 0)
            continue;

         // Process the entries from the sub-directory.
         subDirectoryLi = getentries(&subDirctoryNumEntries, path, level + 1);
         for ( i = 0; i < subDirctoryNumEntries; ++i, ++n )
         {
            if(n >= size){
               size <<= 1;
               li = realloc(li, size*sizeof(ML_ENTRY*));
            }
            li[n] = subDirectoryLi[i];
         }
      }
      if (rv < 0)
         continue;
      li[n] = malloc(sizeof(ML_ENTRY));
      li[n]->ml_name = strdup(entry->d_name);
      li[n++]->ml_size = st.st_size;
   }
   closedir (dir);
   *num_entries = n;
   return li;
}