在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.o
all: $(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的命令了。在后续的工作中,如果有遇到针对目录以及里面相关文件的管理操作,就可以在这个例子的基础上进行快速改装了。