递归搜索目录以查找C中的最大文件

Searching directories recursively for largest files in C

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

(这也是我第一次 post 在这里,所以如果还有什么我在格式化 post 方面做错的,也请告诉我。)

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

你说,

For some reason though, the program does not seem to be adding the information for the subdirectory files to the array.

在你的函数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;
}