用C语言区分Linux上的文件和目录

a14dhokn  于 2023-03-17  发布在  Linux
关注(0)|答案(2)|浏览(143)

我有一个函数,它接受一个文件路径参数,然后将该路径与readdir函数和stat函数结合使用,以打印出目录中的所有文件和目录。我遇到的问题是,当我尝试对文件和目录进行排序时,它们都被视为目录。我在这里看过类似的例子,我相信问题是我的统计格式的方式。我只是不我不明白stat是如何工作的,我甚至看过手册页,但它们没有太大意义。
下面是我的代码:

void scan(const char *dir) {
    DIR *directory;
    struct dirent *file;
    struct stat info;

    directory = opendir(dir);

    if (directory == NULL) {
        printf("Cannot open directory: %s\n", dir);
        return;
    }
    while ((file = readdir(directory)) != NULL) {
        if (file->d_name[0] == '.') {
            // then hidden file, so leave hidden
            continue;
        }
        
        if (stat(dir, &info) == -1) {
            printf("can't find %s\n", file->d_name);
            perror("ERROR");
        }

        // determine if file or directory
        if (S_ISREG(info.st_mode))
            printf("File: ");
        if (S_ISDIR(info.st_mode))
            printf("Dir: ");

        // display the name of the file
        printf("%s\n", file->d_name);
    }
    closedir(directory);
}

这是我不断得到的输出...

Dir: par_hash_table.c
Dir: BlackBoxTesting
Dir: Makefile
Dir: in3.txt
Dir: par_hash_table.o
Dir: in5.txt
Dir: par_hash_table
Dir: in4.txt
Dir: in6.txt
Dir: in1.txt
Dir: in2.txt
Dir: in8.txt
Dir: in7.txt

这是我使用的命令,我使用的是Linux,文件路径不需要如此特殊,但我只是想显示所有内容...

./par_hash_table 1 2 /home/dpb/Documents/CSE_420/P3

任何帮助我弄清楚如何区分txt文件和文件夹都会有帮助。

9gm1akwq

9gm1akwq1#

dirent结构中的文件名连接到路径上以使stat()工作的替代方法是使用fstatat(),而不是目录的文件描述符和纯文件名。
另外,在某些文件系统上,readdir()将用文件类型填充dirent结构的d_type字段,因此如果是这种情况,您可以不做任何stat操作。
示例(还包括对错误报告和处理的一些改进;代码的一个问题是即使函数失败也要继续并测试stat结构):

#define _DEFAULT_SOURCE
#define _POSIX_C_SOURCE 200809L
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>

void scan(const char *dir) {
    DIR *directory;
    struct dirent *file;

    directory = opendir(dir);

    if (directory == NULL) {
      fprintf(stderr, "Cannot open directory %s: %s\n", dir, strerror(errno));
      return;
    }
    int dfd = dirfd(directory); // directory's file descriptor

    while ((file = readdir(directory)) != NULL) {
      if (file->d_name[0] == '.') {
        // then hidden file, so leave hidden
        continue;
      }

      if (file->d_type == DT_UNKNOWN) {
        // Only stat the file if we don't already have the file type available
        struct stat info;
        if (fstatat(dfd, file->d_name, &info, 0) < 0) {
          fprintf(stderr, "Can't stat %s/%s: %s\n",
                  dir, file->d_name, strerror(errno));
          continue;
        }
        if (S_ISREG(info.st_mode)) {
          file->d_type = DT_REG;
        } else if (S_ISDIR(info.st_mode)) {
          file->d_type = DT_DIR;
        }
      }

      // determine if file or directory
      if (file->d_type == DT_REG)
        printf("File: ");
      else if (file->d_type == DT_DIR)
        printf("Dir: ");
      else
        printf("Other: ");

      // display the name of the file
      printf("%s\n", file->d_name);
    }

    closedir(directory);
}

int main(int argc, char **argv) {
  if (argc != 2) {
    fprintf(stderr, "Usage: %s DIRECTORY\n", argv[0]);
    return 1;
  }
  scan(argv[1]);
  return 0;
}
pgpifvop

pgpifvop2#

您的错误在这里:

if(stat(dir, &info) == -1){
        printf("can't find %s\n", file->d_name);
        perror("ERROR");
       }

你每次都要为函数参数dir获取stat,你想从目录条目中获取文件,所以你需要连接目录和文件名,以获取stat的完整路径。
连接部件的代码:

char filepath[strlen(dir) + 1 + strlen(file->d_name) + 1];
snprintf(filepath, sizeof filepath, "%s/%s", dir, file->d_name);
if(stat(filepath, &info) == -1){
   ....

(顺便提一句,这是我认为使用VLA可以的极少数情况之一。如果将其转换为递归函数,请小心,确保VLA在递归调用之前超出作用域......或者仅使用mallocfree以避免堆栈溢出。)
另外,请通过自动格式化器运行您的代码,它也可以添加缺少的可选{}。为每个块使用{}确实是一个很好的主意,即使它只是一个语句。或者,如果您没有找到C自动格式化器,您的编辑器至少应该有自动缩进,所以自己添加{},然后自动缩进代码。

相关问题