【问题标题】:How can I get only txt files from directory in c?如何从 c 目录中仅获取 txt 文件?
【发布时间】:2012-10-19 14:47:08
【问题描述】:

我想只获取给定目录中 *.txt 文件的名称,如下所示:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <dirent.h>

int main(int argc, char **argv)
{
    char *dirFilename = "dir";

    DIR *directory = NULL;

    directory = opendir (dirFilename);
    if(directory == NULL)
        return -1;

    struct dirent *ent;

     while ((ent = readdir (directory)) != NULL)
     {
         if(ent->d_name.extension == "txt")
            printf ("%s\n", ent->d_name);
     }

    if(closedir(directory) < 0)
        return -1;

    return 0;
}

如何在纯 unixs c 中做到这一点?

【问题讨论】:

    标签: c unix char dirent.h


    【解决方案1】:

    首先,Unix 没有文件扩展名的概念,所以struct dirent 上没有extension 成员。其次,您不能将字符串与== 进行比较。你可以使用类似的东西

    bool has_txt_extension(char const *name)
    {
        size_t len = strlen(name);
        return len > 4 && strcmp(name + len - 4, ".txt") == 0;
    }
    

    &gt; 4 部分确保文件名.txt 不匹配。

    (从&lt;stdbool.h&gt;获取bool。)

    【讨论】:

      【解决方案2】:

      您就快到了,您只需要检查文件名是否以.txt 结尾。一种方法是使用strcmpstrcasecmpmemcmp

      while ((ent = readdir (directory)) != NULL)
      {
          int len = strlen(ent->d_name);
          if(len > 4 && memcmp(ent->d_name + len - 4, ".txt", 4) == 0)  // only checks lowercase
          {
              // It's a .txt file - now check that it's a regular file
              char filename[PATH_MAX];
              snprintf(filename, sizeof(filename), "%s/%s", dirFilename, ent->d_name);
              struct stat st;
              if(stat(filename, &st) == 0 && S_ISREG(st.st_mode))
              {
                  // It's a regular file - process it
              }
          }
      }
      

      最好通过在完整文件路径上调用stat(2) 并使用S_ISxxx 宏检查st_mode 字段来验证它是常规文件(而不是目录或其他类型的特殊文件)。请注意,readdir 返回的 DIR 结构的 d_type 成员并不总是受支持,因此依赖它不是一个好主意。

      或者,您可以使用glob(3) 函数,而不是使用opendirreaddirclosedir

      glob_t globbuf;
      if(glob("/path/to/dir/*.txt", 0, NULL, &globbuf) == 0)
      {
        int i;
        for(i = 0; i < globbuf.gl_pathc; i++)
          process_filename(globbuf.gl_pathv[i]);
      }
      globfree(&globbuf);
      

      【讨论】:

      • 您缺少memcmp 的最后一个参数。此外,stricmp 不是标准(C 或 POSIX)函数,而 strcasecmp 是(POSIX)。但是 +1 建议 stat
      • @AdamRosenfield:好的,我也需要检查一下,(类型)谢谢:)
      【解决方案3】:

      @BartFriedrich 指出了glob() 函数,但他没有给出它的使用示例。非常简短(并且完全未经测试)你可以尝试这样的事情

      #include <glob.h>
      #include <stdio.h>
      
      void glob_example() {
          glob_t g;
          int i;
          glob("*.txt", 0, NULL, &g);
          for (i = 0; i < g.gl_pathc) 
              printf("matched: %s\n", g.pathv[i]);
          globfree(&g)
      }
      

      glob() 在细节上实际上是一个相当复杂的函数,对于更一般的文件匹配要求我可能不会使用它,但它确实可以有效地解决您的问题。有关更多信息,请在您的 linux 机器上查看 man glob 或查看 the man page online

      【讨论】:

      • 哎呀。没有注意到巴特弗里德里希已经在他的问题中添加了一个类似的例子。
      【解决方案4】:

      您可以为此使用glob() 函数调用。使用您最喜欢的搜索引擎、Linux 手册页或here 了解更多信息。

      #include <glob.h>
      #include <stdio.h>
      
      int main(int argc, char **argv) {
        const char *pattern = "./*.txt";
        glob_t pglob; 
      
        glob(pattern, GLOB_ERR, NULL, &pglob);      
      
        printf("Found %d matches\n", pglob.gl_pathc);
        printf("First match: %s\n", pglob.gl_pathv[0]);
      
        globfree(&pglob);
      
      
        return 0;
      }
      

      【讨论】:

        【解决方案5】:

        可能性:

        while ((ent = readdir (directory)) != NULL)
        {
            const size_t len = strlen(ent->d_name);
            if (len > 4                     &&
                ent->d_name[len - 4] == '.' &&
                ent->d_name[len - 3] == 't' &&
                ent->d_name[len - 2] == 'x' &&
                ent->d_name[len - 1] == 't')
            {
                printf ("%s\n", ent->d_name);
            }
        }
        

        【讨论】:

          【解决方案6】:

          你可以写一个endswith函数:

          int endswith (const char *name, const char *suffix)
          

          只需通过后缀进行反向循环(从末尾开始)并检查每个字符是否相同。

          【讨论】:

            猜你喜欢
            • 2023-03-26
            • 1970-01-01
            • 1970-01-01
            • 2021-11-06
            • 2015-07-03
            • 1970-01-01
            • 1970-01-01
            • 2011-10-31
            • 2011-08-08
            相关资源
            最近更新 更多