Linux C 实现ls -l 的功能

ls -l

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

//\033(e)[显示方式;前景色;背景色m\033(e)[0m

void get_mode(struct stat buff)//得到当前的文件类型和三个权限

{

char *ptr;

unsigned int i,mask = 0700;

static char *perm[]={"---","--x","-w-","-wx","r--","r-x","rw-","rwx"};//分别对应0 1 2 3 4 5 6 7

if(S_ISREG(buff.st_mode))

ptr="-";

else if(S_ISDIR(buff.st_mode))

ptr="d";

else if(S_ISLNK(buff.st_mode))//符号连接

ptr="l";

printf("%s",ptr);

for(i=3;i;i--)

{

printf("%3s",perm[(buff.st_mode&mask)>>(i-1)*3]);//我们得到的3位8进制数 从左到右分别是 右边没有参与运算的处理掉

mask >>= 3;//mask是掩码

}

}

void get_name(struct stat buff)//得到属主名字 和 属主所在的组 名字

{

struct passwd *user=NULL;//定义一个用户的结构体

struct group *group=NULL;//定义一个组的结构体

user=getpwuid(buff.st_uid);//文件属主的用户身份标识

printf(" %s",user->pw_name);//得到这个标识结构体中的用户名字

group = getgrgid(buff.st_gid);//文件属主的分组身份标识

printf("    %s",group->gr_name);

}

void get_time(struct stat buff)//最新的内容修改时间

{

char *month[]={"1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"};

struct tm *mptr=NULL;//时间结构体

mptr = localtime(&buff.st_mtime);//文件内容方面的上次被修改时间 atime上次被访问时间 ctime文件权限\属主\分组或内容方面的上次被修改时间 这个函数取得文件的时间

printf(" %4s %2d ",month[mptr->tm_mon],mptr->tm_mday);

printf("%02d:%02d",mptr->tm_hour,mptr->tm_min);

}

void list_info(struct stat buff)//文件类型的就列出各种函数得到的结果

{

get_mode(buff);

printf("%5d",buff.st_nlink);//得到硬链接

get_name(buff);

printf("%12ld",buff.st_size);//文件大小

get_time(buff);

}

void list_dir(char *dir_path)//是目录类型的 就

{

int i;

static int count = 0;

DIR *dirp=NULL;//一个文件目录指针

struct dirent *dp=NULL;//存储目录中的文件信息的结构体

struct stat buff;//存储文件信息的结构体

dirp=opendir(dir_path);//打开一个子目录并建立一个子目录流

chdir(dir_path);//进入这个子目录流

while((dp=readdir(dirp)) != NULL)//读这个子目录流是否有内容readdir函数读取到的文件名存储在结构体dirent的d_name成员中

{

if(dp->d_name[0]=='.')//隐藏文件

continue;

if(lstat(dp->d_name,&buff)==-1)//函数lstat的作用就是获取文件名为d_name的文件的详细信息,存储在stat结构体中

{

printf("fail to get stat\n");

continue;

}

for(i = 0;i

{

printf(" \t",count);

}

list_info(buff);

if(S_ISREG(buff.st_mode))

{

printf(" %s\n",dp->d_name);

}

        else if(S_ISDIR(buff.st_mode))

{

printf(" \e[1;34m%s\e[0m\n",dp->d_name);

count++;//再次深入

list_dir(dp->d_name);//自身递归 直到该层的目录中的文件列表读完了 才出来

count--;//递归出来深入减1

}

      else if(S_ISLNK(buff.st_mode))//如果是链接

{

char sbuf[128];

memset(sbuf,'\0',128);

if(readlink(dp->d_name,sbuf,128)!=-1)//成功找到源

{

printf(" \e[0;36m%s\e[0m -> %s\n",dp->d_name,sbuf);

}else{

printf("error\n");

}

}

}//一直读取到这一层目录文件列表完成

chdir("..");//返回到上级目录

}

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

{

int i;

struct stat buff;//定义stat的结构体

if(argc<2)//缺少给定的参数文件

{

printf("loss argument\n");

return -1;

}

for(i=argc-1;i>=1;i--)

{

if(lstat(argv[i],&buff)==-1)// lstat,是一种文件描述词。意思是获取一些文件相关的信息,成功执行时,返回0。失败返回-1

{

printf("%s error\n",argv[i]);

continue;

}

if(S_ISREG(buff.st_mode))//文件是一个普通文件

        {

list_info(buff);

printf(" %s\n",argv[i]);

}

        else if(S_ISDIR(buff.st_mode))//文件是一个子目录

        {

list_dir(argv[i]);

}

else if(S_ISLNK(buff.st_mode))//文件是一个符号链接

        {

list_info(buff);

char sbuf[128];

memset(sbuf,'\0',128);//用‘\0’填充字符串sbuf

if(readlink(argv[i],sbuf,128)!=-1)//readlink取得符号链接所指的文件readlink()会将参数path 的符号连接内容存到参数sbuf 所指的内存空间, 返回的内容不是以NULL作字符串结尾, 但会将字符串的字符数返回. 若参数bufsiz 小于符号连接的内容长度, 过长的内容会被截断.执行成功则传符号连接所指的文件路径字符串

{

printf(" \e[0;36m%s\e[0m -> %s\n",argv[i],sbuf);

}else{

printf("error\n");

}

}

printf("\n");

}

}

你可能感兴趣的:(Linux C 实现ls -l 的功能)