Linux C读取目录

yeotifhr  于 2023-10-16  发布在  Linux
关注(0)|答案(3)|浏览(100)

你好,我想读和写一个目录就像阅读和写文件。我总是使用openreadwriteclose函数,这意味着我使用描述符。但是在目录上这样做不起作用,open调用起作用,但是read返回-1,而errno是EISK。我是否被迫使用流来读取目录?

zazmityj

zazmityj1#

read()write()系统调用不能用于目录。相反,getdents()/getdents64()系统调用用于读取目录。目录根本不能直接写入。
但是,glibc并没有为getdents()/getdents64()系统调用提供 Package 器,而是提供了符合POSIX的readdir()函数,该函数使用这些系统调用实现。大多数程序应该使用readdir(),但也可以直接使用syscall()调用系统调用。

jum4pzuy

jum4pzuy2#

我在Stack Overflow(How can I get the list of files in a directory using C or C++?)中找到了这段代码,这对我理解它的工作原理有很大帮助:

#include <dirent.h>
#include <stdio.h>
#include <string.h>

int main(){
    DIR* dirFile = opendir( "." );
    struct dirent* hFile;
    if ( dirFile ) 
    {
    while (( hFile = readdir( dirFile )) != NULL ) 
    {
       if ( !strcmp( hFile->d_name, "."  )) continue;
       if ( !strcmp( hFile->d_name, ".." )) continue;

     // in linux hidden files all start with '.'
       if ( gIgnoreHidden && ( hFile->d_name[0] == '.' )) continue;

     // dirFile.name is the name of the file. Do whatever string comparison 
     // you want here. Something like:
        if ( strstr( hFile->d_name, ".c" ))
           printf( "found an .txt file: %s", hFile->d_name );
    } 
  closedir( dirFile );
 }
}
fiei3ece

fiei3ece3#

正如@caf所指出的,您应该使用readdir来实现此目的。实际上,使用opendirreaddirclosedir的序列来阅读目录文件。但是,目录是只读的,不能写入。但是,如果您对使用getdents * 系统调用 * 读取目录感到好奇,这里有一个没有错误检查的最小示例。在这里,函数read_dirent获取与目录对应的文件描述符,并在每次调用时返回一个目录条目。目录名可以作为命令行参数传递。默认行为打印当前工作目录的内容。您可以在herehere中阅读有关getdents的更多信息。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/syscall.h>

#define BUF_SIZE 1024

typedef struct linux_dirent 
{
    long           d_ino;
    off_t          d_off;
    unsigned short d_reclen;
    char           d_name[];
} LinuxDirEnt;

LinuxDirEnt *read_dirent(int fd);

int main(int argc, char *argv[])
{
    int fd;
    LinuxDirEnt *d;

    fd = open(argc > 1 ? argv[1] : ".", O_RDONLY);

    printf("inode#  d_reclen  d_name\n");
    while(d = read_dirent(fd))
        printf("%8ld  %4d  %s\n", d->d_ino, d->d_reclen, d->d_name);   

    exit(EXIT_SUCCESS);
}

LinuxDirEnt *read_dirent(int fd)
{
    static int nread = 0;
    static int bpos = 0;
    static char buf[BUF_SIZE];
    static LinuxDirEnt *d;
    
    if (nread == 0)
    {
        nread = syscall(SYS_getdents, fd, buf, BUF_SIZE);
        if (nread == 0)
            return NULL;
        bpos = 0;
    }
    else
        bpos += d->d_reclen;
    d = (LinuxDirEnt *)(buf + bpos);
    nread -= d->d_reclen; 

    return d;
}

相关问题