递归搜索目录以查找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;
}
这个程序的目标是获取目录的命令行参数,并打印该目录(包括子目录)下的前 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;
}