📄 myfind.c
字号:
#include <stdio.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>
#include <fnmatch.h>
#include <time.h>
#include <ctype.h>
#include <sys/stat.h>
char * last_char_is(const char *s, int c)//是用字符指针返回s的最后一个字符
{
char *sret;
if (!s)
return NULL;
sret = (char *)s+strlen(s)-1;
if (sret>=s && *sret == c) {
return sret;
} else {
return NULL;
}
}
extern char *concat_path_file(const char *path, const char *filename)
{
char *outbuf;
char *lc;
if (!path)
path="";
lc = last_char_is(path, '/'); //调用了last_char_is函数
while (*filename == '/')
filename++;
outbuf = (char*)malloc(strlen(path)+strlen(filename)+1+(lc==NULL));
sprintf(outbuf, "%s%s%s", path, (lc==NULL)? "/" : "", filename);
return outbuf;
}
#undef DEBUG_RECURS_ACTION
//这个是主要函数的定义了,注意定义的参数含义
int recursive_action(const char *fileName,
int recurse, int followLinks, int depthFirst,
int (*fileAction) (const char *fileName,
struct stat * statbuf,
void* userData),
int (*dirAction) (const char *fileName,
struct stat * statbuf,
void* userData),
void* userData)
{
int status;
struct stat statbuf; //文件结构
struct dirent *next; //目录结构
if (followLinks == 1) //如果不是links
status = stat(fileName, &statbuf); // 调用stat把传进来要从哪开始查找的文件或目录的结构赋给statbuf
else
status = lstat(fileName, &statbuf); // 调用lstat 有区别
if (status < 0) { //如果要在哪查都不知道当然别查了
#ifdef DEBUG_RECURS_ACTION //如果定义了Recurs则 一种错误返回
fprintf(stderr,
"status=%d followLinks=%d TRUE=%d\n",
status, followLinks, 1);
#endif //没有则另一种返回,这里我们没定义
printf("%s", fileName);
return 0;
}
//如果是要开始查找地方本身是文件或目录的链接
// if ((followLinks == 0) && (S_ISLNK(statbuf.st_mode))) { if (followLinks == 0) {
if (fileAction == NULL)
return 1;
else //如果存在则直接进行匹配显示出链接
return fileAction(fileName, &statbuf, userData);
}
if (recurse == 0) { //如果是recurse,这里我们都定义的true
// if (S_ISDIR(statbuf.st_mode)) {
if (dirAction != NULL)
return (dirAction(fileName, &statbuf, userData));
else
return 1;
// }
}
//这开始对目录进行查询 相应的文件
if (S_ISDIR(statbuf.st_mode)) {
DIR *dir;
if (dirAction != NULL && depthFirst == 0) { //开始进行查找,先用status得到diraction的状态
status = dirAction(fileName, &statbuf, userData);
if (status == 0) { //如果没查到,则错误
printf("此文件不存在%s", fileName);
return 0;
}
}
dir = opendir(fileName); //把目录打开,以便在下级查
if (!dir) {
printf("文件不存在:%s", fileName);
return 0;
}
status = 1;
while ((next = readdir(dir)) != NULL) { // 读取下级所有文件 依次匹配
char *nextFile;
//如果碰到"."".."的文件则跳向下一个,因为没用
if ((strcmp(next->d_name, "..") == 0)
|| (strcmp(next->d_name, ".") == 0)) {
continue;
}
//对每个文件调用concat_path_file函数,该函数主要是用nextFile返回把filename和next->d_name给连接起来的值,形成所查找新值的全路径
nextFile = concat_path_file(fileName, next->d_name);
if (recursive_action(nextFile, 1, followLinks, depthFirst,
fileAction, dirAction, userData) == 0) {
//接下来在对新的nextFile进行递归的recursive_action查找,直到找到最下一级目录
status = 0;
}
free(nextFile);
}
closedir(dir); //打开的就要关闭
//如果调用recursive存在目录,且
if (dirAction != NULL && depthFirst == 1) { //如果 当depthfirst 为true时的一种情况,这里也不用。
if (dirAction(fileName, &statbuf, userData) == 0) {
printf("文件不存在%s", fileName);
return 0;
}
}
if (status == 0)
return 0;
} else { //如果不是目录则调用fileAction查找返回
if (fileAction == NULL)
return 1;
else
return fileAction(fileName, &statbuf, userData);
}
return 1;
}
static char *pattern; //放要查找的文件名
static int fileAction(const char *fileName, struct stat *statbuf, void* junk)
{ //该函数比较filename和statbuf是否匹配,是则输出,就是判断文件是否匹配
if (pattern != NULL) { //要查找的文件不为NULL
const char *tmp = strrchr(fileName, '/'); //找到最后一个/后的字符,例如/home/zx/xx 则找到xx
if (tmp == NULL)
tmp = fileName;
else
tmp++; //tmp指向xx 文件名或目录名
if (!(fnmatch(pattern, tmp, FNM_PERIOD) == 0))
return 1; //判断是否匹配,如果是则不输出,不是则输出
}
puts(fileName); //如果匹配证明查到则输出文件名 如输出xx的全路径包括了目录路径
return 1; //不能匹配则返回,继续查找
}
int main(int argc, char **argv) //主函数
{
int dereference = 0; //这是用来控制文件是否是连接类型的,初始为FALSE
int i, firstopt, status = EXIT_SUCCESS;//EXIT_SUCCESS定义在stlib.h中
//完成查找功能,其中fileAction是指针函数,完成的是文件和查找文件匹配的功能,“."是指查找路径。
if (recursive_action(".", 1, dereference, 0, fileAction,
fileAction, NULL) == 0)
{printf("error");status = EXIT_FAILURE;}
//如果指定了查找目录则从指定的目录开始搜索 同样调用recursive_action
else for (i = 1; i < firstopt; i++) {
if (recursive_action(argv[i], 1, dereference, 0, fileAction,
fileAction, NULL) == 0)
status = EXIT_FAILURE;
}
return status;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -