在 Linux 系统中,opendir()
函数用于打开一个目录流,以便后续使用其他相关函数(如 readdir()
)读取目录中的内容。然而,opendir()
本身并不直接提供获取目录属性的功能。要获取目录的属性,可以使用 dirent
结构体结合其他系统调用或库函数。以下是几种常用的方法:
stat()
函数stat()
函数可以获取文件或目录的详细信息。通过传递目录路径给 stat()
,可以获得包括权限、所有者、大小、修改时间等在内的多种属性。
示例代码:
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>
int main() {
DIR *dir = opendir(".");
if (dir == NULL) {
perror("opendir");
return EXIT_FAILURE;
}
struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
if (entry->d_type == DT_DIR) { // 只处理目录
char path[1024];
snprintf(path, sizeof(path), "./%s", entry->d_name);
struct stat st;
if (stat(path, &st) == -1) {
perror("stat");
continue;
}
printf("目录名称: %s\n", entry->d_name);
printf("大小: %ld 字节\n", st.st_size);
printf("权限: ");
printf((S_ISDIR(st.st_mode)) ? "d" : "-");
printf((st.st_mode & S_IRUSR) ? "r" : "-");
printf((st.st_mode & S_IWUSR) ? "w" : "-");
printf((st.st_mode & S_IXUSR) ? "x" : "-");
printf((st.st_mode & S_IRGRP) ? "r" : "-");
printf((st.st_mode & S_IWGRP) ? "w" : "-");
printf((st.st_mode & S_IXGRP) ? "x" : "-");
printf((st.st_mode & S_IROTH) ? "r" : "-");
printf((st.st_mode & S_IWOTH) ? "w" : "-");
printf((st.st_mode & S_IXOTH) ? "x" : "-\n");
printf("最后修改时间: %s", ctime(&st.st_mtime));
}
}
closedir(dir);
return EXIT_SUCCESS;
}
说明:
opendir(".")
打开当前目录。readdir(dir)
读取目录中的每一个条目。snprintf()
构建完整的路径。stat(path, &st)
获取该路径的详细信息,并存储在 struct stat
结构体中。st.st_mode
的值,打印目录的权限和其他属性。dirent
结构体中的 d_type
从 Linux Kernel 2.6.15 开始,dirent
结构体新增了 d_type
字段,可以用来判断目录条目的类型(如文件、目录、符号链接等)。这使得无需调用 stat()
即可部分获取目录属性。
示例代码:
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <unistd.h>
int main() {
DIR *dir = opendir(".");
if (dir == NULL) {
perror("opendir");
return EXIT_FAILURE;
}
struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
if (entry->d_type == DT_DIR) { // 只处理目录
printf("目录名称: %s\n", entry->d_name);
}
}
closedir(dir);
return EXIT_SUCCESS;
}
说明:
d_type
可以是 DT_REG
(常规文件)、DT_DIR
(目录)、DT_LNK
(符号链接)等。stat()
更高效,但功能较为有限,无法获取详细属性。getdents()
系统调用getdents()
是一个低级的系统调用,可以直接读取目录条目并获取更多信息,适用于需要高性能的场景。
示例代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>
int main() {
int fd = open(".", O_RDONLY);
if (fd == -1) {
perror("open");
return EXIT_FAILURE;
}
struct dirent *buf = malloc(1024);
if (buf == NULL) {
perror("malloc");
close(fd);
return EXIT_FAILURE;
}
ssize_t n = syscall(SYS_getdents, fd, buf, sizeof(buf));
if (n == -1) {
perror("getdents");
free(buf);
close(fd);
return EXIT_FAILURE;
}
for (ssize_t i = 0; i < n; ) {
struct linux_dirent *de = (struct linux_dirent *)(buf + i);
char path[1024];
snprintf(path, sizeof(path), "./%s", de->d_name);
if (de->d_type == DT_DIR) { // 只处理目录
printf("目录名称: %s\n", de->d_name);
}
i += de->d_reclen;
}
free(buf);
close(fd);
return EXIT_SUCCESS;
}
说明:
open()
打开目录。syscall(SYS_getdents, ...)
读取目录条目。linux_dirent
结构体,判断类型并处理。注意:
getdents()
是一个低级接口,通常需要包含 <linux/dirent.h>
并使用特定的结构体 linux_dirent
,这在不同的 Linux 版本中可能有所不同。虽然 opendir()
本身只能用于打开目录流,但结合其他系统调用(如 stat()
)或利用 dirent
结构体中的新字段(如 d_type
),可以实现获取目录属性的功能。选择具体方法时,应根据需求权衡性能和功能复杂度。