Подсчет файлов для каждого подкаталога - программа на C (POSIX) - PullRequest
0 голосов
/ 03 ноября 2019

Я полный новичок в программировании на C с использованием POSIX. Я пытаюсь написать программу, которая считает файлы в каждом подкаталоге, начиная с каталога, указанного в переменной среды. Для каждого подкаталога программа должна написать в stdout короткое сообщение:

Каталог: 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;
}

Это вывод "find [...]введите -f "для каталога в переменной env" DIR ":

./.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 несколько раз (по крайней мере, это то, что я сделал на этом этапе).

Я пытался использовать флаги FTW_CHDIR и FTW_DEPTH, но вывод показал только каталог из переменной env "DIR" со счетом == 0;

На данный момент, я потерян и понятия не имеюкак написать эту программу по-другому, чтобы выполнить задачу.

Любые идеи / помощь будут оценены :).

1 Ответ

1 голос
/ 03 ноября 2019

В идеале, вы хотите, чтобы поиск в ширину (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
}

Ссылки:

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