在Linux下,需要实现某个目录下文件的遍历的时候,可以使用opendir,readdir,closedir这些接口。这些接口使用说明如下所示:
1).opendir
DIR* opendir(const char * name);
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);
传入name路径,成功则返回非空DIR指针,否则返回NULL; 注意DIR前面没有struct,如果加上编译器会warning。
2).readdir
struct dirent *readdir(struct DIR* dir);
readdir一般要配合opendir使用,readdir不是线程安全函数,代替他的有readdir_r。
readdir返回 struct dirent *指针,读完目录下所有文件时,返回NULL。
3).closedir
void closedir(DIR* dir); 关闭打开的目录描述符dir,同时释放dir空间。Closedir需要配合opendir使用。
下面简单记录下这些接口的使用例子,主要涉及文件遍历,文件查找,文件模糊查找,文件删除,关键字查找并删除等功能。
1.首先在Linux系统下,在这里创建一个命名为"proj"测试的工程。
2.创建一个名为“dirtest.c”的源文件,粘贴如下所示的内容:
#include<stdio.h>
#include<stdlib.h>
#include <stdarg.h>
#include <sys/types.h>
#include <dirent.h>
#include<string.h>//定义一些文件操作的宏
#define MODE_LIST_ALL_FILE 0 //列出所有文件
#define MODE_FIND_FILE 1 //查找一个文件
#define MODE_DELETE_FILE 2 //删除一个文件
#define MODE_FUZZY_SEARCH_FILE 3 //通过关键字匹配查找文件
#define MODE_FUZZY_SEARCH_DELETE_FILE 4 //通过关键字匹配查找并删除文件/*
函数功能:列出该目录下的所有文件
*/
void list_all_files(DIR *dir)
{int index=0;struct dirent *d;while ((d = readdir(dir)) != NULL){index++;LOG("[index %d]:%s\n", index, d->d_name); }}
/*
函数功能:查找文件
返回:1,成功找到;0:未找到文件
*/int find_files(DIR *dir, char *file)
{struct dirent *d;int find = 0;while ((d = readdir(dir)) != NULL){
//如果名称匹配上,则打印出该文件名称提示if(!strcmp(d->d_name, file)) {LOG("Locate the file named%s\n", d->d_name);find = 1;//返回结果置1}}return find;
}
/*
函数功能:通过关键字匹配查找文件
返回:1,成功找到;0:未找到文件
*/int fuzzy_search_files(DIR *dir, char *keyword)
{struct dirent *d;int find = 0;while ((d = readdir(dir)) != NULL){
//如果名称匹配上,则打印出该文件名称提示if(strstr(d->d_name, keyword)) {LOG("file :%s match!!!\n", d->d_name);find = 1;//返回结果置1}}return find;
}/*
函数功能:删除一个文件
返回:1,成功找到,并删除该文件;0:未找到文件
*/
int delete_files(DIR *dir, char *test_dir, char *file)
{struct dirent *d;int find = 0;while ((d = readdir(dir)) != NULL){if(!strcmp(d->d_name, file)) {char delete_file[64]="";sprintf(delete_file, "%s/%s", test_dir, file);//需要将路径+文件名才能正确删除unlink(delete_file);LOG("delete file:%s success!\n", delete_file);find = 1;}}return find;
}
/*
函数功能:删除通过关键字匹配上的文件
返回:1,成功找到,并删除该文件;0:未找到文件
*/
int delete_files_by_keyword(DIR *dir, char *test_dir, char *keyword)
{struct dirent *d;int find = 0;while ((d = readdir(dir)) != NULL){if(strstr(d->d_name, keyword)) {char delete_file[64]="";sprintf(delete_file, "%s/%s", test_dir, d->d_name);//需要将路径+文件名才能正确删除unlink(delete_file);LOG("delete file:%s success!\n", delete_file);find = 1;}}return find;
}
/*
函数功能:接收并解析命令行输入的参数
返回:无
*/void dir_proc(char *argv[])
{char *dir_name = argv[1];int cmd_code = atoi(argv[2]);DIR *dir;struct dirent *d;dir = opendir(dir_name);if (!dir){LOG("cannot open dir %s", dir_name);return ;}//根据代号,作出不同的操作switch(cmd_code) {case MODE_LIST_ALL_FILE:{//显示该目录下的所有文件list_all_files(dir);break;}case MODE_FIND_FILE:{
//查找文件if(argv[3]) {if(!find_files(dir,argv[3])) {LOG("file name %s not found!\n", argv[3]);}}else {show_help();}break;}case MODE_DELETE_FILE:{
//删除文件if(argv[3]) {if(!delete_files(dir,argv[1], argv[3])) {LOG("file name %s not found!delete fail\n", argv[3]);}}else {show_help();}break;}case MODE_FUZZY_SEARCH_FILE:{//通过关键字查找文件if(argv[3]) {if(!fuzzy_search_files(dir, argv[3])) {LOG("file name search by keywords %s fail!\n", argv[3]);}}else {show_help();}break;}case MODE_FUZZY_SEARCH_DELETE_FILE:{//通过关键字查找,并删除文件if(argv[3]) {if(!delete_files_by_keyword(dir,argv[1], argv[3])) {LOG("file name search by keywords %s fail!\n", argv[3]);}}else {show_help();}break;}default:{LOG("command unkown!\n");break;}}closedir(dir);
}
3.创建一个名为”main.c”的文件,内容如下所示:
#include<stdio.h>
#include<stdlib.h>
#include <stdarg.h>
#include <sys/types.h>
#include <dirent.h>
#include<string.h>/*
函数功能:日志打印
*/
void LOG(const char *format,...)
{va_list argptr;char buffer[2048];va_start(argptr,format);vsprintf(buffer,format,argptr);va_end(argptr);printf("%s", buffer);
}
/*
函数功能:显示菜单选项
*/
void show_help()
{LOG("Invalid parameter!\n");LOG("-h:Show help\n");LOG("0:List all files\n");LOG("1:Find a file, (for example: ./dirtest test_dir 1 a.txt)\n");LOG("2:Delete a file, (for example: ./dirtest test_dir 2 a.txt)\n");LOG("3:Fuzzy find file, (for example: ./dirtest test_dir 3 a)\n");LOG("4:Delete files by keyword, (for example: ./dirtest test_dir 4 a)\n");
}
/*
程序入口
*/
int main(int argc, char *argv[])
{LOG("run dir test!\n");if(argc<3) {show_help();exit(0);}dir_proc(argv);return 0;
}
4.创建一个编译的Makefile,方便编译整个工程,内容如下所示:
CPROG = dirtest #生成一个名为dirtest的目标文件
BIN = $(CPROG)
CC= gcc
OBJS=main.o dirtest.oall: $(BIN)
clean:rm -f $(OBJS) $(BIN)
$(BIN): $(OBJS)$(CC) -o $(BIN) $(OBJS) $(CFLAGS) $(LDFLAGS) $(CFLAGS_EXTRA)
5.创建完dirtest.c,main.c,Makefile后,便可以编译了,在该工程目录下执行make clean;make,编译成功之后会生成一个名为 “dirtest”的可执行文件。如下图所示:
6.测试,在该路径下创建一个名为“test_dir”的目录,然后随意创建一些文件。如下图所示:
6.1列出路径下的所有文件
6.2查找文件
6.3删除文件
6.4关键字查找文件
6.5通过关键字查找,并删除文件
至此,上述功能已简单测试完毕。
总结:关于目录的操作例子就写到这里了,熟悉了这些操作,自然而然地可以自己先ls的命令了。在后续的工作中,如果有遇到针对目录以及里面相关文件的管理操作,就可以在这个例子的基础上进行快速改装了。