简单find命令的实现

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了简单find命令的实现相关的知识,希望对你有一定的参考价值。

贴代码:

/*实现一个简单的find命令:*/
/*程序思路:首先,用一个单链表将所需要的信息存储起来;其次根据所传入的参数信息,改变节点的状态(若有这个状态,证明该节点就是我们所需要的)
最后将所需要的信息(文件名)打印出来,释放节点存储空间 */
/*加上一些信息:若仅仅运行程序(没有输入的参数),则将当前的目录输出,若仅仅只有1个参数(必须为目录)将该目录下的信息输出,接下来根据所给的
参数信息,执行相应的操作 */

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<string.h>
#include<dirent.h>
#include<sys/stat.h>

char *name;//保存输入的参数(名字)

/*每一个节点就是一个文件的所有信息*/
typedef struct Node
{
char name[30];//存放文件的名称;
struct stat info;//存放文件的属性
int flag;//设置的状态
struct Node * pNext;//指针域
}File;

File *GetInfo(char dirname[]);
void do_find(int argc, char *argv[], File *pHead);
void do_free(File *pHead);
void change_name_flag(File *pHead);
void print(File *pHead);
void change_size_flag(File *, long);
void change_dir_flag(File *);
void change_cdev_flag(File *);
void change_bdev_flag(File *);
void change_gid_flag(File *, long);
void change_uid_flag(File *, long);


int main(int argc, char *argv[])
{

File *pHead = GetInfo(".");
do_find(argc, argv, pHead);
print(pHead);

return 0;
}

/*将当前目录里面所需要的所有信息均保存在了所定义的结构体中*/
File * GetInfo(char dirname[])
{
File * pHead = (File *)malloc(sizeof(File));//构造一个头节点
if (pHead == NULL)
exit(-1);
pHead->pNext = NULL;
File *pTail = pHead;//设置一个尾指针,方便循环体里将所有节点链接

DIR *dir_ptr;
struct dirent *direntp;
if ((dir_ptr = opendir(dirname)) == NULL)//打开目录
fprintf(stderr, "cannot open %s\n", dirname);
else
{
while ((direntp = readdir(dir_ptr)) != NULL)//读取目录
{
File *pNew = (File *)malloc(sizeof(File));//生成一个新节点
if (pNew == NULL)
exit(-1);
strcpy(pNew->name, direntp->d_name);/*给数据域赋值*/
if (stat(pNew->name, &(pNew->info)) == -1)
perror(pNew->name);
pNew->flag = 1;
pTail->pNext = pNew;
pNew->pNext = NULL;
pTail = pNew;
}
closedir(dir_ptr);
}
return pHead;
}

void do_free(File *pHead)
{
File *p = pHead;
while (pHead != NULL)
{
p = pHead->pNext;
free(pHead);
pHead = p;
}
}
/*具体思路:比如:当传入-name时,就要去判断改变name的状态,但是怎样*/
/*根据传入的参数执行相应的操作*/

void do_find(int argc, char *argv[], File *pHead)
{
int i=2;
while (i < argc)
{
if (strcmp(argv[i], "-name") == 0)//判断输入的参数是否是-name
{
if (i+1 < argc)//判断后面是否还有输入
{
name = argv[i+1];
change_name_flag(pHead);
}
else
{
printf("input name error!\n");
do_free(pHead);//先释放空间,然后退出
exit(-1);
}
}
else if(strcmp(argv[i], "-size") == 0) //尺寸输入的是数字,但是是作为字符被识别的,因此需要使用字符串转数字的函数(atoi)
{
if (i+1<argc)
{
change_size_flag(pHead, atoi(argv[i+1]));
}
else
{
printf("input size error!\n");
do_free(pHead);
exit(-1);
}
}
else if(strcmp(argv[i], "-type") == 0)/*下面这两处代码不规整,健壮性不够, 具体参见上面的写法*/
{
if (strcmp(argv[i+1], "-d") == 0)
change_dir_flag(pHead);
else if (strcmp(argv[i+1], "-") == 0)
change_file_flag(pHead);
else if (strcmp(argv[i+1], "-b") == 0)
change_bdev_flag(pHead);
else if (strcmp(argv[i+1], "-c") == 0)
change_cdev_flag(pHead);
else
{
}
}
else if (strcmp(argv[i], "-gid") == 0)/*通过id命令可以查看当前的用户号,查找时也是通过用户号进行查找*/
{
change_gid_flag(pHead, atoi(argv[i+1]));
}
else if (strcmp(argv[i], "-uid") == 0)
{
change_uid_flag(pHead, atoi(argv[i+1]));
}
else
{}
i+=2;
}
}

void change_name_flag(File *pHead)//应该对目录中的每一项进行一个遍历
{
File *p = pHead->pNext;
while (p != NULL)
{
if (strstr(p->name, name) == NULL && p->flag == 1)//说明在节点中没有与name相同的信息,标志设为0
p->flag = 0;
p = p->pNext;
}
}

void change_size_flag(File * pHead, long size)//atoi(argv[i+1])的结果是把字符串转换为数字(本例中的size)
{
File *p = pHead->pNext;
while (p != NULL)
{
if ((p->info).st_size > size && p->flag == 1)
p->flag = 0;
p = p->pNext;
}
}

void change_dir_flag(File *pHead)
{
File *p = pHead->pNext;
while (p != NULL)
{
if (!S_ISDIR(p->info.st_mode) && p->flag == 1)
p->flag = 0;
p = p->pNext;
}
}


void change_file_flag(File *pHead)
{
File *p = pHead->pNext;
while (p != NULL)
{
if (!S_ISREG(p->info.st_mode) && p->flag == 1)
p->flag = 0;
p = p->pNext;
}
}


void change_bdev_flag(File *pHead)
{
File *p = pHead->pNext;
while (p != NULL)
{
if (!S_ISBLK(p->info.st_mode) && p->flag == 1)
p->flag = 0;
p = p->pNext;
}
}


void change_cdev_flag(File *pHead)
{
File *p = pHead->pNext;
while (p != NULL)
{
if (!S_ISCHR(p->info.st_mode) && p->flag == 1)
p->flag = 0;
p = p->pNext;
}
}

void change_gid_flag(File *pHead, long gid)
{
File * p = pHead->pNext;
while (p != NULL)
{
if (p->info.st_gid != gid && p->flag == 1)
p->flag = 0;
p = p->pNext;
}
}

void change_uid_flag(File * pHead, long uid)
{
File * p = pHead->pNext;
while (p != NULL)
{
if (p->info.st_uid != uid && p->flag == 1)
p->flag = 0;
p = p->pNext;
}
}

void print(File *pHead)//打印出所需要的信息(对节点的每一项进行一个遍历,如果状态为1,则将之打印出来)
{
File * p = pHead->pNext;
while (p != NULL)
{
if (p->flag == 1)
{
printf("%s\n", p->name);
}
p = p->pNext;
}
}

 

以上是关于简单find命令的实现的主要内容,如果未能解决你的问题,请参考以下文章

find命令简述

Cmake命令之find_package介绍

Linux命令grep和find相关使用

如何用python写一个简单的find命令

find命令的简单使用

如何使用find命令实现只查当前目录,而不查其子目录