计算每个子目录的文件 - C (POSIX) 中的程序

标签 c linux posix

我完全是使用 POSIX 进行 C 编程的初学者。 我正在尝试编写一个程序,该程序从环境变量中给定的目录开始计算每个子目录中的文件。对于每个子目录,程序应向标准输出写入一条短消息:

目录:name_of_dir
文件:num_of_files

我试过用 nftw() 编写这样的程序。


#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define _XOPEN_SOURCE 500
#include <ftw.h>

#define MAXFD 20

int files = 0; // files count for each subdirectory
int files_main = 0; // files count for the directory from env variable DIR
int k = 0;
int l = 0;

char prev_dir[100];
char current_dir[100];

void print_dir() // helper function to print current directory
{
  char current_dir[100];
  getcwd(current_dir, 100);

  printf("Directory: %s \n", current_dir);
}

void print_files() // helper function to print number of files
{
  printf("Files: %d \n", files);
}

int search(const char *name, const struct stat *s, int type, struct FTW *f)
{

  getcwd(current_dir, 100);

  if(strcmp(prev_dir, current_dir) != 0 && l == 1) // check if the directory has changed, l as a flag to omit printing the same directory path more than once
  {
    l = 0;
    print_files();
    files = 0;
    strcpy(prev_dir, current_dir);
  }

  if(strcmp(current_dir, getenv("DIR")) == 0) // counting files in directory from env variable DIR
  {
    switch (type)
    {
      case FTW_F: files_main++; break;
    }
  }

  else // counting files for each subdirectory
  {
    getcwd(prev_dir, 100);
    if(l==0)
    {
      print_dir();
      l = 1;
    }

    switch (type)
    {
      case FTW_F: files++; break;
    }
  }
  return 0;
}

int main(int argc, char ** argv)
{
  strcpy(prev_dir, getenv("DIR")); // getting the dir from env variable

  nftw(getenv("DIR"), search, depth, FTW_CHDIR);
  printf("Directory: %s \n", getenv("DIR"));
  printf("Files: %d \n", files_main);

  return EXIT_SUCCESS;
}

这是环境变量“DIR”中目录的“find [...] type -f”的输出:

./.DS_Store
./playground2
./playground3
./playground
./playground.c
./test_dir1/test1.txt
./test_dir1/test2.txt
./Makefile
./playground3.c
./test_file.txt
./playground2.c
./test_dir2/test3.tst
./dir1/p.tet
./dir1/sfsdfsdf/dfsd.txt
./dir1/ofi/test
./dir1/ofi/test2
./link_by_link_function

这是我运行 C 程序时的输出:


$ ./playground2

Directory: /Users/<user>/Desktop/C POSIX/Playground 
Files: 5 
Directory: /Users/<user>/Desktop/C POSIX/Playground/test_dir1 
Files: 2 
Directory: /Users/<user>/C POSIX/Playground 
Files: 4 
Directory: /Users/<user>/C POSIX/Playground/test_dir2 
Files: 1 
Directory: /Users/<user>/C POSIX/Playground/dir1 
Files: 1 
Directory: /Users/<user>/Desktop/C POSIX/Playground/dir1/sfsdfsdf 
Files: 1 
Directory: /Users/<user>/Desktop/C POSIX/Playground/dir1/ofi 
Files: 2 
Directory: /Users/<user>/Desktop/C POSIX/Playground 
Files: 1 
Directory: /Users/<user>/Desktop/C POSIX/test_dir1 
Files: 2 
Directory: /Users/<user>/Desktop/C POSIX/test_dir2 
Files: 1 
Directory: /Users/<user>/Desktop/C POSIX 
Files: 19 

程序没有按预期运行,查看输出后很明显。 “files_main”计数器也适用于 [...]/Playground/子目录的计数器似乎工作正常。问题是 [...]/Playground/目录本身。 当程序多次进入 [...]/Playground 目录时,计数器"file"在检测到目录更改后重置,这不是一个好的解决方案(至少这是我此时得出的结论)。

我已尝试使用 FTW_CHDIR 和 FTW_DEPTH 标志,但输出仅显示来自环境变量“DIR”且计数 == 0 的目录;

在这一点上,我迷路了,不知道如何以不同的方式编写这个程序来完成任务。

任何想法/帮助将不胜感激:)。

最佳答案

理想情况下,您希望广度优先搜索 (BFS) 进行计数。使用 BFS,在进入下一个目录(向下或向上)之前处理每个目录。不幸的是,nftw 正在实现深度搜索优先 (DFS)。

您可以使用 FTW 结构(搜索函数的参数 f)解决计数限制。它包括成员“级别”。您可以维护一组计数器,每个级别一个,而不是保留一个计数器,它将在文件夹更改时重置为零。

另请注意,搜索函数已传递足够的信息,因此无需保留状态(current_dir、prev_dir、...)、检测更改等。

static int file_count[50] ; // Assuming big enough.

static int search(const char *name, const struct stat *s, int type, struct FTW *f)
{
   static int file_count[50] ;
   // Count
   if ( f->level < 50 ) { file_count[f->level]++ ;} ;
   if ( type == FTW_DP ) {
       // Last entry for folder
       printf("Folder: %s files: %d\n", name, file_count[f->level+1]) ;
       file_count[f->level+1] = 0 ;
   } ;
   return 0 ;
}

main (...) 
{
   Invoke nftw with FTW_DP
}

链接:

关于计算每个子目录的文件 - C (POSIX) 中的程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58680812/

相关文章:

c - 无法打印二叉树中的所有元素

c - 当给出额外输入时,如何使 Visual Studio 2015 中的控制台输出窗口保持打开状态?

c - 如何在avr中存储十进制格式的数字

c - 长字符串数据的暂存

c - 关于htonl的源码

c - Thales Connect HSM - DeriveKey 操作

php - 检查用户是否是root

c - 循环中 printf 的 Getline 行为

windows - Windows x64 是否有任何 POSIX 兼容层?

c - POSIX 部分写入()