ls -l这个查询所输出的分别是文件的权限信息、硬链接数、用户id、组id、文件大小、最后访问时间、文件名;这些都在stat结构体里面、stat结构体以下:数组
/*用不到的成员被注释掉,只需了解须要的成员便可*/ struct stat{ //dev_t st_dev;/*设备id号*/ //ino_t st_ino;/*i节点号*/ mode_t st_mode;/*权限与文件类型*/ nlink_t st_nlink;/*硬连接数*/ uid_t st_uid;/*用户id*/ ggid_t st_gid;/*所在组id*/ //dev_t st_rdev;/*设备id,对于特殊文件才有*/ off_t st_size;/*大小,较为经常使用*/ //blksize_t st_blocks;/*blocksize for file system I/O*/ //blkcnt_t st_blksize;/*number of 512B blocks allocated*/ //time_t st_atime;/*最后的访问时间*/ time_t st_mtime;/*最后的修改时间,较为经常使用*/ //time_t st_ctime;/*最后的状态改变时间*/ }
这个题目我的以为有些技巧性,首先是9个权限位信息,那么就要想到mode的权限管理,那么,上课所讲的mode_t mode哦按段文件类型的宏函数、表示文件权限与类型的宏变量就是不可少的:socket
S_ISREG(m) is it a regular file?/*判断是不是普通文件*/ S_ISDIR(m) directory?/*判断是不是目录*/ S_ISCHR(m) character device?/*判断是不是字符设备*/ S_ISBLK(m) block device?/*判断是不是块设备*/ S_ISFIFO(m) FIFO (named pipe)?/*判断是不是管道文件*/ S_ISLNK(m) symbolic link? (Not in POSIX.1-1996.)/*判断使是不是符号连接(软链接)*/ S_ISSOCK(m) socket? (Not in POSIX.1-1996.)/*判断是不是SOCKET文件*/
另外就是时间,要充分利用<time.h>里面的tm结构体,注意到最后利用localtime进行转换。函数
#include<sys/types.h> #include<sys/stat.h> #include<time.h> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<dirent.h> #include<unistd.h> #include<pwd.h> #include<grp.h> /** m:mode权限,这个请看前面解释 str: */ char* get_mode(mode_t mode,char* str)//显示文件读写权限函数 { if(S_ISREG(mode)) strcpy(str,"-");//普通文件 else if(S_ISDIR(mode)) strcpy(str,"d");//目录文件 else if(S_ISCHR(mode)) strcpy(str,"c");//字符设备文件 else if(S_ISBLK(mode)) strcpy(str,"b");//块设备文件 else if(S_ISFIFO(mode)) strcpy(str,"p");//管道文件 else if(S_ISLNK(mode)) strcpy(str,"l");//连接文件 else if(S_ISSOCK(mode)) strcpy(str,"n");//socket文件 /**断定文件访问权限的屏蔽字 这里使用strcat的巧妙之处就在于联想到是到最后字符串,那么这里将所需的权限按照顺序拼接,只需对比,那么就能够输出这里是否有访问的权限 思路来源:leetcode中的题解*/ // 属主权限 strcat(str,mode&S_IRUSR?"r":"-");//判断是否用户可读 strcat(str,mode&S_IWUSR?"w":"-");//判断用户是否可写 strcat(str,mode&S_IXUSR?"x":"-");//判断用户有无执行权限 // 同组权限 strcat(str,mode&S_IRGRP?"r":"-");//判断组有无读权限 strcat(str,mode&S_IWGRP?"w":"-");//判断组有无写特权 strcat(str,mode&S_IXGRP?"x":"-");//判断组有无可执行权限 // 其它权限 strcat(str,mode&S_IROTH?"r":"-");//判断其余有无读权限 strcat(str,mode&S_IWOTH?"w":"-");//判断其余我有无写权限 strcat(str,mode&S_IXOTH?"x":"-");//判断其余有无写权限 return str;//返回拼接完成的字符串,即为要求的9位字符串 } /** 这里须要明确 一是Unix时间是从1970年1月1日0时0分0秒开始,用秒差形式,那么在结构体stat中有time_t st_time(最后修改时间)做为标准来进行打印 二是在c语言中,<time.h>有来判断时间tm结构体,计算机大多数状况使用的都是time_t,由于他的效率高,可是显示位tm结构形式,localtime()实现time_t到tm的转换,time_t的指针做为参数,返回值tm的指针 思路来源:学校acm题库 */ void time_ch(struct stat *message)//经过秒数来计算日期 { struct tm * chtm = localtime(&(message->st_mtime));//这个在上面注释中已经详细说明,再也不赘述 if(chtm == NULL){ printf("localtime is error"); exit(0); } else{ printf("%d月 %d ",chtm->tm_mon+1,chtm->tm_mday);//tm_mom属于[0,11] } if(chtm->tm_hour < 10)//0-9要转换成0x形式 printf("0");//先打印0 printf("%d:",chtm->tm_hour);//在打印x printf("%d ",chtm->tm_min);//打印分钟不存在0x问题 //对比ls -l,没有秒 } void list_nlink(const struct stat *message){//打印出硬链接数 printf("%d ",message->st_nlink); } /** 对于main里面参数的理解 * argc: 整数,为传给main()的命令行参数个数。 * argv: 字符串数组。 * env: 安符串数组。env[] 的每个元素都包含ENVVAR=value形式的字符串。其中ENVVAR为环境变量如PATH或87。value 为ENVVAR的对应值如C:\DOS,C:\TURBOC(对于PATH)或YES(对于87)。 */ int main(int argc,char** argv,char** environ)//主函数 { char* dir_name=NULL;//文件名字 if(argc == 1)//第一个参数,那么按道理来说,他应该是根目录(我的的猜想,没有获得验证) { dir_name="."; } else if(argc == 2)//第二个参数,即为文件 { dir_name = argv[1];//获取文件名字 } else//当位3或者更大时,那么已经不是一个文件,退出程序 { puts("it isn't a dir"); return -1; } DIR* fd = opendir(dir_name);//打开文件 if(NULL == fd)//判断错误并处理 { perror("opendir"); return -1; } struct dirent* de=readdir(fd);//定义接收readdir函数返回的结构体变量,判断是读取文件 for(;de;de=readdir(fd))// { if('.'==de->d_name[0]) continue; //经过文件名得到文件信息 struct stat s; int ret = lstat(de->d_name,&s);//用lstat函数读取filename文件的信息,并将结果返回到stat结构体中 if(0 > ret)//stat函数出错进行信息输出 { perror("stat is error"); return -1; }//stat函数不出错则进行信息输出 char str[11] = {};//用于9个标志位所需 printf("%s ",get_mode(s.st_mode,str));//类型 list_nlink(&s); struct passwd *passwd; passwd = getpwuid(s.st_uid); printf ("%s ", passwd->pw_name);//主名 struct group *group; group = getgrgid(passwd->pw_gid); printf ("%s ", group->gr_name); //组名 printf("%5lu ",s.st_size);//大小 time_ch(&s);//时间 printf("%s\t",de->d_name);//文件名 printf("\n"); } closedir(fd);//关闭文件 }
进行测试,发现了本身其中的不足,没有排序以及没有总用量,而且没有对与在使用的打亮。若是有解决的,欢迎指正。测试