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

时间:2014-05-30 15:23:03

标签: c linux shell readdir opendir

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

输出应该是这样的:

 << ./Program testDirectory

 Dir directory1
 lnk linkprogram.c
 reg file.txt

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

#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;
}

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

4 个答案:

答案 0 :(得分:19)

d_type是一种速度优化,可以在lstat(2)次来电时保存。{/ p>

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

如果仅使用d_type==DT_UNKNOWN,如果单独的文件名不足以决定它是无趣的,那么您总是需要使用lstat(2)的代码。 (对于某些呼叫者来说就是这种情况,例如find -name或者像*.c那样扩展整体,这就是为什么readdir不会产生填充它的开销的原因。额外的磁盘读取。)

Linux getdents(2)手册页有一个示例程序,可以执行您尝试执行的操作,包括将d_type字段解码为文本字符串的链式三元运算符块。 (正如其他答案所指出的那样,你的错误就是把它打印成一个角色,而不是将它与DT_REGDT_DIR等进行比较。)

无论如何,其他答案主要涵盖了一些内容,但在d_type == DT_UNKNOWN(Linux上为0。d_type的情况下错过了需要后退的关键细节。曾经是一个填充字节,直到Linux 2.6.4)。

为了便携,您的代码需要检查struct dirent是否有d_type字段,如果您使用它,或者您的代码甚至无法编译在GNU和BSD系统之外。 (见readdir(3)


我为finding directories with readdir 编写了示例,当d_type在编译时不可用时使用d_type并回退到stat。 #39; s DT_UNKNOWN,以及符号链接。

答案 1 :(得分:4)

返回结构中的d_type给出了该类型的数字。您无法直接打印,因为在解释为ASCII时,所使用的值不可打印(例如,dirs为4,文件为8。)

你可以将它们打印成这样的数字:

printf("%d ", dent->d_type)

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

if(dent->type == DT_DIR) type = 'd'

答案 2 :(得分:2)

d_type打印为如下所示的整数:

printf("%d ", dent->d_type);

你会看到有意义的价值观。

答案 3 :(得分:0)

我能够在ubuntu上使用d_type:

    switch (readDir->d_type)
    {
    case DT_DIR:
        printf("Dir: %s\n", readDir->d_name);
        break;
    case DT_REG:
        printf("File: %s\n", readDir->d_name);
        break;
    default:
        printf("Other: %s\n", readDir->d_name);
    }

条目类型的列表可以在dirent.h中找到(对于ubuntu以外的其他操作系统可能有所不同):

dirent.h

#define DT_UNKNOWN       0
#define DT_FIFO          1
#define DT_CHR           2
#define DT_DIR           4
#define DT_BLK           6
#define DT_REG           8
#define DT_LNK          10
#define DT_SOCK         12
#define DT_WHT          14