检查一个目录.readdir返回的条目是目录,链接或文件

Bar*_*ers 8 c linux dirent.h readdir opendir

我正在制作一个在Linux shell中运行的程序,并接受一个参数(一个目录),并显示目录中的所有文件及其类型.

输出应该是这样的:

 << ./Program testDirectory

 Dir directory1
 lnk linkprogram.c
 reg file.txt
Run Code Online (Sandbox Code Playgroud)

如果没有参数,则使用当前目录.这是我的代码:

#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>

int main(int argc, char *argv[])
{
  struct stat info;
  DIR *dirp;
  struct dirent* dent;

  //If no args
  if (argc == 1)
  {

    argv[1] = ".";
    dirp = opendir(argv[1]); // specify directory here: "." is the "current directory"
    do
    {
      dent = readdir(dirp);
      if (dent)
      {
        printf("%c ", dent->d_type);
        printf("%s \n", dent->d_name);

        /* if (!stat(dent->d_name, &info))
         {
         //printf("%u bytes\n", (unsigned int)info.st_size);

         }*/
      }
    } while (dent);
    closedir(dirp);

  }

  //If specified directory 
  if (argc > 1)
  {
    dirp = opendir(argv[1]); // specify directory here: "." is the "current directory"
    do
    {
      dent = readdir(dirp);
      if (dent)
      {
        printf("%c ", dent->d_type);
        printf("%s \n", dent->d_name);
        /*  if (!stat(dent->d_name, &info))
         {
         printf("%u bytes\n", (unsigned int)info.st_size);
         }*/
      }
    } while (dent);
    closedir(dirp);

  }
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

由于某种原因dent->d_type,不显示文件类型.我不确定该怎么办,有什么建议吗?

Pet*_*des 21

d_type是一种速度优化lstat(2),可以在支持时保存通话.

正如readdir(3)手册页指出的那样,并非所有文件系统都在该d_type字段中返回实际信息(通常是因为需要额外的磁盘搜索来读取inode,如果您不使用XFS的情况就是如此mkfs.xfs -n ftype=1(暗示-m crc=1哪个)还不是默认值.总是设置的文件系统DT_UNKNOWN在现实生活中很常见,而不是你可以忽略的东西.XFS不是唯一的例子.

你总是需要的代码,将回退到使用lstat(2)如果d_type==DT_UNKNOWN,如果单独的文件名是不够的,决定它的无趣.(对于某些呼叫者来说就是这种情况,比如find -name扩展整数*.c,这就是为什么readdir如果需要额外的磁盘读取就不会产生填充的开销.)

Linux getdents(2)手册页有一个示例程序,可以执行您要执行的操作,包括一个链式三元运算符块,用于将d_type字段解码为文本字符串.(至于其他的答案指出,你的错误是打印出来作为一个字符,而不是它比较对DT_REG,DT_DIR等等)

无论如何,其他的答案大多覆盖的东西,但错过了关键的细节,你需要一个备用当箱子d_type == DT_UNKNOWN(0在Linux上. d_type存储在曾经被认为是一个填充字节,直到Linux的2.6.4).

为了便于移植,您的代码需要检查struct dirent即使是一个d_type字段,如果您使用它,或者您的代码甚至不会在GNU和BSD系统之外编译.(见readdir(3))


我写了一个使用readdir查找目录的示例,使用d_typestat退到d_type在编译时,DT_UNKNOWN和符号链接时不可用.


use*_*046 5

d_type在返回结构给出了类型的数字。您不能直接打印它,因为当解释为 ASCII 时,使用的值不可打印(例如,它们是 4 表示目录,8 表示文件。)。

您可以将它们打印为这样的数字:

printf("%d ", dent->d_type)
Run Code Online (Sandbox Code Playgroud)

或者将它们与类似的常量进行比较,并从中DT_DIR构建一些有意义的输出,比如 char 类型:

if(dent->type == DT_DIR) type = 'd'
Run Code Online (Sandbox Code Playgroud)