Linux文件系统调用----实现对树形文件结构的广度优先遍历,即按层输出文件信息

本文介绍了如何实现对Linux文件系统的广度优先遍历,以层次结构输出文件信息。通过定义队列数据结构并结合系统调用,程序能够遍历指定目录及其子目录,显示文件的大小和修改时间。

#include <unistd.h>

#include <stdio.h>

#include <stdlib.h>

#include <errno.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <dirent.h>

#include <time.h>

#include <string.h>

#include <ctype.h>

#include"malloc.h"

#define true 1

#define false 0

#define Datatype char

//队列的数据结构,用链表方式实现

typedef struct node{

    Datatype data[1024];//结点数据域,用于存放路径

    struct node *next;//结点指针域

}QueueNode;//结点的结构体

 

typedef struct{

    QueueNode *front;//队首

    QueueNode *rear;//队尾

}LinkQueue,*PQUEUE;//队列的结构体

 

//初始化队列

void InitQueue(PQUEUE Q)

{

    Q->front = Q->rear = NULL;

}

 

//判断队列是否为空

int QueueEmpty(PQUEUE Q)

{

    return(Q->front == NULL && Q->rear == NULL);

}

 

//入队

void EnLinkQueue(PQUEUE Q, Datatype *v)

{

    QueueNode *p;

    p = (QueueNode *)malloc(sizeof(QueueNode));

    strcpy(p->data , v);

    p->next = NULL;

    if(QueueEmpty(Q)) Q->front = Q->rear = p;

    else

    {

        Q->rear->next = p;  

        Q->rear = p;         

    }

}

 

//出队

void DeLinkQueue(PQUEUE Q,Datatype *i)

{

 

    QueueNode *s;

    if(QueueEmpty(Q))  {   //如果队列为空,报错

        printf("Error,the linkqueue is empty!");

        return;

    }

    s = Q->front;

    strcpy(i , s->data);

    if(Q->front == Q->rear)

        Q->front = Q->rear = NULL;

    else

        Q->front = s->next;

    free(s);

}

 

static int get_file_size_time(const char *filename)

{

        struct stat statbuf;

        if(stat(filename,&statbuf) == -1)

        {

                printf("Get start on %s Error:%s\n",filename,strerror(errno));

                return(-1);

        }

        if(S_ISDIR(statbuf.st_mode))

        {

                return(1);//判断是否是目录

        }

        if(S_ISREG(statbuf.st_mode))

                printf("%s size:%ld bytes\tmodified at %s",filename,statbuf.st_size,ctime(&statbuf.st_mtime));

        return(0);//若是普通文件,则处处文件路径,大小和修改时间

}

 

int cursive(PQUEUE Q,char *argv)//遍历队列中的目录

{

        DIR *dirp;

        struct dirent *direntp;

        int stats,stat;

        char path1[1024];

        char pathtmp[1024];

 

        if(((stats = get_file_size_time(argv))==0)||(stats==-1))

                exit(1);

        if((dirp=opendir(argv))==NULL)

        {

                printf("Open Directory %s Error:%s\n",argv,strerror(errno));

                exit(1);

        }

        while((direntp = readdir(dirp))!=NULL)

        {

                strcpy(path1,argv);

                strcat(path1,"/");

                strcat(path1,direntp->d_name);

                stat=get_file_size_time(path1);

                if(stat==-1)

                        break;

  if(stat==1&&path1[strlen(path1)-1]!='.'){

                        EnLinkQueue(Q,path1);

                }//如果是子目录文件,则将该路径加入队列

        }//遍历完当前层的普通文件

       //开始取出下一层的路径,准备遍历下一层

        if(QueueEmpty(Q) == 0)

        {//如果队列不空,则从中取出路径

            char fullpath[1024];

            memset(fullpath,0,1024);

            DeLinkQueue(Q,pathtmp);

            strcpy(fullpath,pathtmp);

            cursive(Q,fullpath);//遍历目录中的文件

        }

        closedir(dirp);

        return 0;

}

int main(int argc,char **argv)

{//逻辑似cursive()函数

        DIR *dirp;

        struct dirent *direntp;

        int stats;

        char path[1024];

        char pathtmp[1024];

        LinkQueue qst;

        PQUEUE Q=&qst;

        InitQueue(Q);//初始化队列

        int stat;

        if(argc!=2)

        {

                printf("Usage:%s filename\n\a",argv[0]);

                exit(1);

        }

         if(((stats = get_file_size_time(argv[1]))==0)||(stats==-1))

                    exit(1);

         if((dirp=opendir(argv[1]))==NULL)

            {

                    printf("Open Directory %s Error:%s\n",argv[1],strerror(errno));

                    exit(1);

            }

            while((direntp = readdir(dirp))!=NULL)      

  {

                    memset(path,0,1024);

                    strcpy(path,argv[1]);

                    strcat(path,"/");

                    strcat(path,direntp->d_name);

                    stat=get_file_size_time(path);

                    if(stat==-1)

                            break;

  if(stat==1&&path[strlen(path)-1]!='.')

                           EnLinkQueue(Q,path);

            }

        if(!QueueEmpty(Q))

        {

            char fullpath[1024];

            memset(fullpath,0,1024);

            DeLinkQueue(Q,pathtmp);

            strcpy(fullpath,pathtmp);

            cursive(Q,fullpath);

        }

        closedir(dirp);

        exit(1);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值