【问题标题】:Counting the number of files in a directory using C使用C计算目录中的文件数
【发布时间】:2010-11-10 10:04:21
【问题描述】:

如何在linux平台上使用C计算目录中的文件数。

【问题讨论】:

    标签: c linux file


    【解决方案1】:

    不保证这段代码可以编译,它实际上只与 Linux 和 BSD 兼容:

    #include <dirent.h>
    
    ...
    
    int file_count = 0;
    DIR * dirp;
    struct dirent * entry;
    
    dirp = opendir("path"); /* There should be error handling after this */
    while ((entry = readdir(dirp)) != NULL) {
        if (entry->d_type == DT_REG) { /* If the entry is a regular file */
             file_count++;
        }
    }
    closedir(dirp);
    

    【讨论】:

    • 如果要处理子目录中的文件,遇到目录项时可以递归。确保排除“。”和“..”如果你这样做。
    • 很好地捕捉到了不同的包含。
    • 是的,它们是 POSIX 函数。
    • POSIX 仅将 d_ino 和 d_name 指定为 dirent 结构的成员。此代码测试特定于平台的 d_type。
    • 如果有人想知道为什么你必须循环遍历以及为什么没有函数可以在恒定时间内获取目录中有多少文件,我发现了这个:blogs.msdn.com/b/oldnewthing/archive/2009/02/17/9426787.aspx
    【解决方案2】:

    readdir

    【讨论】:

      【解决方案3】:

      如果你不关心当前目录.和父目录..这样的:

      drwxr-xr-x  3 michi michi      4096 Dec 21 15:54 .
      drwx------ 30 michi michi     12288 Jan  3 10:23 ..
      

      你可以这样做:

      #include <stdio.h>
      #include <sys/types.h>
      #include <sys/stat.h>
      #include <dirent.h>
      #include <string.h>
      #include <stdlib.h>
      #include <unistd.h>
      
      int main (void){
          size_t count = 0;
          struct dirent *res;
          struct stat sb;
          const char *path = "/home/michi/";
      
          if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)){
              DIR *folder = opendir ( path );
      
              if (access ( path, F_OK ) != -1 ){
                  if ( folder ){
                      while ( ( res = readdir ( folder ) ) ){
                          if ( strcmp( res->d_name, "." ) && strcmp( res->d_name, ".." ) ){
                              printf("%zu) - %s\n", count + 1, res->d_name);
                              count++;
                          }
                      }
      
                      closedir ( folder );
                  }else{
                      perror ( "Could not open the directory" );
                      exit( EXIT_FAILURE);
                  }
              }
      
          }else{
              printf("The %s it cannot be opened or is not a directory\n", path);
              exit( EXIT_FAILURE);
          }
      
          printf( "\n\tFound %zu Files\n", count );
      }
      

      输出:

      1) - .gnome2
      2) - .linuxmint
      3) - .xsession-errors
      4) - .nano
      5) - .kde
      6) - .xsession-errors.old
      7) - .gnome2_private
      8) - Public
      9) - .gconf
      10) - .bashrc
      11) - .macromedia
      12) - .thunderbird
      13) - Pictures
      14) - .profile
      15) - .cinnamon
      16) - .pki
      17) - Compile
      18) - Desktop
      19) - .Private
      20) - .cache
      21) - .Xauthority
      22) - .ICEauthority
      23) - VirtualBox VMs
      24) - .bash_history
      25) - .mozilla
      26) - .local
      27) - .config
      28) - .codeblocks
      29) - Documents
      30) - .bash_logout
      31) - Videos
      32) - Templates
      33) - Downloads
      34) - .adobe
      35) - .gphoto
      36) - Music
      37) - .dbus
      38) - .ecryptfs
      39) - .sudo_as_admin_successful
      40) - .gnome
      
          Found 40 Files
      

      【讨论】:

      • 不是反对者,但您为什么要回答一个近 9 年前就已被接受的问题?你的答案明显更好吗?是否发生了某些变化导致接受的答案无效?
      • @Fureeish 因为 SO 不仅仅针对一个特定的问题/答案。如果您可以向问题提供更多信息,则应该是 SO 答案。这个答案在这里是为了扩展接受的答案。
      • @Fureeish 好的,我明白你的意思。我添加了更多代码(stat 和 access),以使答案与 Accepted 不同。
      【解决方案4】:

      如果您还想包含子目录,您可以使用我在某些代码中使用的这个函数。您可能应该修改它以包含更多错误检查并支持不同的目录分隔符。

      int countfiles(char *path) {
          DIR *dir_ptr = NULL;
          struct dirent *direntp;
          char *npath;
          if (!path) return 0;
          if( (dir_ptr = opendir(path)) == NULL ) return 0;
      
          int count=0;
          while( (direntp = readdir(dir_ptr)))
          {
              if (strcmp(direntp->d_name,".")==0 ||
                  strcmp(direntp->d_name,"..")==0) continue;
              switch (direntp->d_type) {
                  case DT_REG:
                      ++count;
                      break;
                  case DT_DIR:            
                      npath=malloc(strlen(path)+strlen(direntp->d_name)+2);
                      sprintf(npath,"%s/%s",path, direntp->d_name);
                      count += countfiles(npath);
                      free(npath);
                      break;
              }
          }
          closedir(dir_ptr);
          return count;
      }
      

      【讨论】:

        猜你喜欢
        • 2011-12-24
        • 2021-08-25
        • 2014-01-31
        • 2010-10-15
        • 2011-02-17
        • 2016-02-19
        • 1970-01-01
        • 1970-01-01
        • 2011-02-07
        相关资源
        最近更新 更多