Linux系统函数opendir、closedir、readdir详解及案例(自定义ls工具)
Linux系统函数opendir、closedir、readdir详解及案例
- 引言
- 1. Linux系统函数详解
- 1.1 opendir函数
- 1.2 closedir函数
- 1.3 readdir函数
- 2. 案例:自定义ls工具
- 2.1 功能概述
- 2.2 实现代码
- 2.2.1 包含头文件
- 2.2.2 定义函数
- 2.2.3 主函数
- 3. 使用CMake编译
- 3.1 创建CMakeLists.txt
- 3.2 编译步骤
- 3.3 运行
- 4. 总结
引言
在Linux系统编程中,目录操作是非常基础且重要的功能。本文将详细介绍Linux系统中的三个目录操作函数:opendir
、closedir
和readdir
,并结合一个实际案例(自定义ls工具)进行演示,最后附上使用CMake编译的完整实现。
1. Linux系统函数详解
1.1 opendir函数
opendir
函数用于打开一个目录,并返回一个指向DIR
结构体的指针。这个指针可以用于后续的目录操作。
- 函数原型:
DIR *opendir(const char *name);
- 参数:
name
:要打开的目录的路径。
- 返回值:
- 成功时,返回一个
DIR
指针。 - 失败时,返回
NULL
,并设置errno
以指示错误原因。
- 成功时,返回一个
- 头文件:
#include <dirent.h>
示例代码:
DIR *dir = opendir("."); // 打开当前目录
if (dir == NULL) {perror("opendir");exit(EXIT_FAILURE);
}
1.2 closedir函数
closedir
函数用于关闭一个已打开的目录流。
- 函数原型:
int closedir(DIR *dir);
- 参数:
dir
:由opendir
返回的目录流指针。
- 返回值:
- 成功时,返回
0
。 - 失败时,返回
-1
,并设置errno
以指示错误原因。
- 成功时,返回
示例代码:
if (closedir(dir) == -1) {perror("closedir");exit(EXIT_FAILURE);
}
1.3 readdir函数
readdir
函数用于读取目录流中的下一个条目。
- 函数原型:
struct dirent *readdir(DIR *dir);
- 参数:
dir
:由opendir
返回的目录流指针。
- 返回值:
- 成功时,返回一个指向
struct dirent
的指针。 - 失败或到达目录末尾时,返回
NULL
。
- 成功时,返回一个指向
struct dirent
结构体:
struct dirent {ino_t d_ino; // 文件的inode编号off_t d_off; // 文件的偏移量unsigned short d_reclen; // 目录条目记录的长度unsigned char d_type; // 文件类型char d_name[]; // 文件名
};
示例代码:
struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {printf("文件名: %s\n", entry->d_name);
}
2. 案例:自定义ls工具
2.1 功能概述
我们将使用opendir
、readdir
和closedir
函数实现一个简单的ls
工具,功能包括:
- 列出指定目录下的所有文件和子目录。
- 显示文件名、文件类型、文件大小和修改时间。
2.2 实现代码
2.2.1 包含头文件
#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
#include <time.h>
#include <stdlib.h>
2.2.2 定义函数
void print_file_info(const char *path) {struct stat statbuf;if (lstat(path, &statbuf) == -1) {perror("lstat");return;}// 获取文件类型printf("%c ", (statbuf.st_mode & S_IFMT) == S_IFDIR ? 'd' : '-');// 获取文件大小printf("%ld ", statbuf.st_size);// 获取修改时间struct tm *tm = localtime(&statbuf.st_mtime);printf("%02d/%02d/%02d %02d:%02d ", tm->tm_mon + 1, tm->tm_mday, tm->tm_year % 100, tm->tm_hour, tm->tm_min);// 获取文件名printf("%s\n", path);
}void ls(const char *dir_path) {DIR *dir = opendir(dir_path);if (dir == NULL) {perror("opendir");return;}struct dirent *entry;while ((entry = readdir(dir)) != NULL) {if (entry->d_name[0] == '.') {continue; // 跳过隐藏文件}char path[1024];snprintf(path, sizeof(path), "%s/%s", dir_path, entry->d_name);print_file_info(path);}if (closedir(dir) == -1) {perror("closedir");return;}
}
2.2.3 主函数
int main(int argc, char *argv[]) {if (argc != 2) {printf("Usage: %s <directory>\n", argv[0]);return EXIT_FAILURE;}const char *dir_path = argv[1];ls(dir_path);return EXIT_SUCCESS;
}
3. 使用CMake编译
3.1 创建CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(custom_ls)set(CMAKE_C_STANDARD 11)add_executable(ls_main main.c)
target_link_libraries(ls_main pthread)
3.2 编译步骤
mkdir build
cd build
cmake ..
make
3.3 运行
./ls_main /path/to/directory
4. 总结
本文详细介绍了Linux系统中的opendir
、closedir
和readdir
函数,并通过一个自定义的ls
工具案例展示了它们的实际应用。通过本文的学习,读者可以掌握基本的目录操作方法,并能够在此基础上进行更复杂的系统编程开发。