在Linux下使用程序实现ls -l 的功能
需求分析
ls -l 的使用方式
ls -l 的基本使用方式有两种,分别是ls -l +文件名、ls -l +目录,如下图所示:
根据图片中得到的结果分析出,ls -l 命令得到的结果包含有文件类型,权限信息,链接数,用户名,组名,文件大小,最后修改时间,文件名称以及链接文件的目标文件。
故程序的设计要求就是通过用户传入一个文件名或者路径,解析出该文件或者该路径下所有文件的相关信息并按照格式打印到终端上。
功能实现
目录流
打开目录
读取目录
目录流的关闭
获取文件的属性
stat这个结构体是用来描述一个linux系统文件系统中的文件属性的结构,stat结构体的详细属性如下:
struct stat {mode_t st_mode; //文件对应的模式,文件,目录等ino_t st_ino; //inode节点号dev_t st_dev; //设备号码dev_t st_rdev; //特殊设备号码nlink_t st_nlink; //文件的连接数uid_t st_uid; //文件所有者gid_t st_gid; //文件所有者对应的组off_t st_size; //普通文件,对应的文件字节数time_t st_atime; //文件最后被访问的时间time_t st_mtime; //文件内容最后被修改的时间time_t st_ctime; //文件状态改变时间blksize_t st_blksize; //文件内容对应的块大小blkcnt_t st_blocks; //文件内容对应的块数量};
定义一个struct stat sbuf;通过lstat(s,&sbuf)来获取文件属性,其中代表文件路径。
文件的类型
stat结构体中的st_mode则 则定义了下列8个宏:S_IFMT 0170000 文件类型的位遮罩S_IFSOCK 0140000 scoketS_IFLNK 0120000 符号连接S_IFREG 0100000 一般文件S_IFBLK 0060000 区块装置S_IFDIR 0040000 目录S_IFCHR 0020000 字符装置S_IFIFO 0010000 先进先出
st-mode & S_IFMT 的结果即为七大文件类型的宏值之一;所以可以使用switch-case语句来判断文件的类型并进行打印。
//查看文件类型switch(sbuf.st_mode&S_IFMT){case S_IFSOCK: printf("s");break;case S_IFCHR: printf("c");break;case S_IFLNK: printf("l");break;case S_IFREG: printf("-");break;case S_IFBLK: printf("b");break;case S_IFDIR: printf("d");break;case S_IFIFO: printf("p");break; }
另外, 上述的文件类型在POSIX中也定义了检查这些类型的宏定义:
S_ISLNK (st_mode) 判断是否为符号连接
S_ISREG (st_mode) 是否为一般文件
S_ISDIR (st_mode) 是否为目录
S_ISCHR (st_mode) 是否为字符装置文件
S_ISBLK (s3e) 是否为先进先出
S_ISSOCK (st_mode) 是否为socket使用st_mode成员判断文件类型:
if((sb.st_mode & S_IFMT) ==S_IFLNK)
{
printf("连接文件\n");
}if (S_ISREG(sb.st_mode))
{
printf("普通文件\n");
}
文件的权限
S_IRUSR 00400 文件所有者具可读取权限 二进制:100 000 000 1<<8
S_IWUSR 00200 文件所有者具可写入权限 二进制:010 000 000 1<<7
S_IXUSR 00100 文件所有者具可执行权限 二进制:001 000 000 1<<6
S_IRGRP 00040 用户组具可读取权限 二进制:000 100 000 1<<5
S_IWGRP 00020 用户组具可写入权限 二进制:000 010 000 1<<4
S_IXGRP 00010 用户组具可执行权限 二进制:000 001 000 1<<3
S_IROTH 00004 其他用户具可读取权限 二进制:000 000 100 1<<2
S_IWOTH 00002 其他用户具可写入权限 二进制:000 000 010 1<<1
S_IXOTH 00001 其他用户具可执行权限 二进制:000 000 001 1<<0
根据以上关系得出,st_mode &(1<<n)即为该文件的各个权限(0=<n<8=8)。
//查看权限int n=8;for(;n>=0;n--)if(sbuf.st_mode&(1<<n))switch(n%3){case 2: printf("r");break;case 1: printf("w");break;case 0: printf("x");break;}else{printf("-");}
文件的链接数
通过stat结构体中st_nlink属性可以获取文件的链接数。
printf(" %d",sbuf.st_nlink);
文件所属的用户、用户组
用户信息与用户组信息存储分别在struct stat中的st_uid和 st_gid中
getpwuid函数:解码所有者信息
#include <sys/types.h>
#include <pwd.h>
struct passwd *getpwuid(uid_t uid);
struct passwd {
char *pw_name; /* username */
char *pw_passwd; /* user password */
uid_t pw_uid; /* user ID */
gid_t pw_gid; /* group ID */
char *pw_gecos; /* user information */
char *pw_dir; /* home directory */
char *pw_shell; /* shell program */
};
getgrgid函数:解码所属组信息
#include <sys/types.h>
#include <grp.h>struct group *getgrgid(gid_t gid);
struct group {
char *gr_name; /* group name */
char *gr_passwd; /* group password */
gid_t gr_gid; /* group ID */
char **gr_mem; /* NULL-terminated array of pointers
to names of group members */
};
//查看用户名,组名struct passwd *puser;puser=getpwuid(sbuf.st_uid);printf(" %s",puser->pw_name);struct group *pgroup;pgroup=getgrgid(sbuf.st_gid);printf(" %s",pgroup->gr_name);
文件大小
文件大小存储在struct stat 结构体中st_size属性中
//查看大小 printf(" %ld",sbuf.st_size);
文件最后修改时间
文件的最后修改时间信息存储在struct stat 结构体中 st_mtime属性中 ,通过localtime解码时间信息。
struct tm *now_time;now_time=localtime(&sbuf.st_mtime);printf(" %d-%d-%d %d:%d",now_time->tm_year+1900,now_time->tm_mon+1,now_time->tm_mday,now_time->tm_hour,now_time->tm_min);
文件名
//查看文件名printf(" %s",s);
链接文件的目标文件
//链接指向目标文件char buf[128]={0};if((sbuf.st_mode&S_IFMT)==S_IFLNK){readlink(s,buf,sizeof(buf));printf("-->%s\n",buf);}elseprintf("\n");
程序设计
设计思想及源码
主程序中使用命令行参数的方式传入文件名或目录,故需要分情况讨论,传入不同的参数执行不同的函数。
int main(int argc, char* argv[])
{if(argc!=2){printf("请输入两个参数!!!\n");return -1;}struct stat sbuf;lstat(argv[1],&sbuf);if(S_ISDIR(sbuf.st_mode)){ //如果是目录dirPath(argv[1]);}else{ //如果是文件名filePath(argv[1]);}return 0;
}
如果传入的是文件名:
void filePath(const char* s)
{struct stat sbuf;lstat(s,&sbuf);//查看文件类型switch(sbuf.st_mode&S_IFMT){case S_IFSOCK: printf("s");break;case S_IFCHR: printf("c");break;case S_IFLNK: printf("l");break;case S_IFREG: printf("-");break;case S_IFBLK: printf("b");break;case S_IFDIR: printf("d");break;case S_IFIFO: printf("p");break; }//查看权限int n=8;for(;n>=0;n--)if(sbuf.st_mode&(1<<n))switch(n%3){case 2: printf("r");break;case 1: printf("w");break;case 0: printf("x");break;}else{printf("-");}//查看链接数printf(" %d",sbuf.st_nlink);//查看用户名,组名struct passwd *puser;puser=getpwuid(sbuf.st_uid);printf(" %s",puser->pw_name);struct group *pgroup;pgroup=getgrgid(sbuf.st_gid);printf(" %s",pgroup->gr_name);//查看大小 printf(" %ld",sbuf.st_size);//查看最后修改时间struct tm *now_time;now_time=localtime(&sbuf.st_mtime);printf(" %d-%d-%d %d:%d",now_time->tm_year+1900,now_time->tm_mon+1,now_time->tm_mday,now_time->tm_hour,now_time->tm_min);//查看文件名printf(" %s",s);//链接指向目标文件char buf[128]={0};if((sbuf.st_mode&S_IFMT)==S_IFLNK){readlink(s,buf,sizeof(buf));printf("-->%s\n",buf);}elseprintf("\n"); }
如果传入的是目录:
首先需要打开目录,然后依次读取目录中的文件进行文件属性获取然后打印,读取结束后关闭目录。
void dirPath(const char* s)
{DIR* dirp=opendir(s);if(dirp==NULL){perror("opendir");return;}struct dirent* fp;while(NULL!=(fp=readdir(dirp))){if(fp->d_name[0]=='.'){continue;}struct stat sbuf;lstat(fp->d_name,&sbuf);//查看文件类型switch(sbuf.st_mode&S_IFMT){case S_IFSOCK: printf("s");break;case S_IFCHR: printf("c");break;case S_IFLNK: printf("l");break;case S_IFREG: printf("-");break;case S_IFBLK: printf("b");break;case S_IFDIR: printf("d");break;case S_IFIFO: printf("p");break; }//查看权限int n=8;for(;n>=0;n--)if(sbuf.st_mode&(1<<n))switch(n%3){case 2: printf("r");break;case 1: printf("w");break;case 0: printf("x");break;}else{printf("-");}//查看链接数printf(" %d",sbuf.st_nlink);//查看用户名,组名struct passwd *puser;puser=getpwuid(sbuf.st_uid);printf(" %s",puser->pw_name);struct group *pgroup;pgroup=getgrgid(sbuf.st_gid);printf(" %s",pgroup->gr_name);//查看大小 printf(" %6ld",sbuf.st_size);//查看最后修改时间struct tm *now_time;now_time=localtime(&sbuf.st_mtime);printf(" %d-%d-%d %2d:%2d",now_time->tm_year+1900,now_time->tm_mon+1,now_time->tm_mday,now_time->tm_hour,now_time->tm_min);//查看文件名printf(" %s",fp->d_name);//链接指向目标文件char buf[128]={0};if((sbuf.st_mode&S_IFMT)==S_IFLNK){ //读取链接文件的指向readlink(fp->d_name,buf,sizeof(buf));printf("-->%s\n",buf);}elseprintf("\n"); }closedir(dirp);
}
实现效果
可以看到对于文件名,./a.out ./a.out和 ls -l ./a.out 的效果一致
对于目录,./a.out ./ 和 ls -l ./的效果一致
在Linux下使用程序实现ls -l 的功能相关推荐
- Linux下ll命令与ls -l
还大三Linux课的债. 1.ll命令用于显示当前文件下非隐藏文件的详情 查询结果分为7栏: 1)如' -rw-r--r--' 表示三种用户对该文件的不同权限: r:可读:w:可写:x:可执行 其中第 ...
- Linux下C程序的编辑,编译和运行以及调试
...
- linux 跟踪程序执行过程,用pvtrace和Graphviz实现对linux下C程序的函数调用跟踪
用pvtrace和Graphviz实现对linux下C程序的函数调用跟踪 用pvtrace和Graphviz实现对linux下C程序的函数调用跟踪 1:功能介绍,使用本方法可以实现linux下C应用程 ...
- Linux常用命令详解 ls -l命令详解
Linux常用命令详解 ls -l命令详解 一.ls -l命令显示效果 使用ls -l会产生长列表格式输出,包含了目录中每个文件的更多的信息. 注:蓝色或/表示目录,如果带绿色或*号表示可执行文件. ...
- 查看linux文件的权限:ls -l 文件名称
查看linux文件的权限:ls -l 文件名称 查看linux文件夹的权限:ls -ld 文件夹名称(所在目录) 修改文件及文件夹权限: sudo chmod -(代表类型)×××(所有者)×××(组 ...
- qt调用linux 进程,Linux 下qt 程序打包发布(使用linuxdelpoyqt ,shell 脚本)
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/u014746574/article/d ...
- Linux 下qt 程序打包发布(使用linuxdelpoyqt ,shell 脚本)
Linux 下qt 程序打包发布(使用linuxdelpoyqt ,shell 脚本) 转载于:https://www.cnblogs.com/zhehan54/p/9549017.html
- linux c++ 程序运行时间,总结UNIX/LINUX下C++程序计时的方法
前言 良好的计时器可帮助程序开发人员确定程序的性能瓶颈,或对不同算法进行性能比较.但要精确测量程序的运行时间并不容易,因为进程切换.中断.共享的多用户.网络流量.高速缓存访问及转移预测等因素都会对程序 ...
- 解决Windows下Arm下Linux下Qt4程序的中文乱码问题
解决Windows下Arm下Linux下Qt4程序的中文乱码问题 ################################################################### ...
最新文章
- 寻找Archie服务器中的文件,Archie服务
- js和css被屏蔽了,拦截器 Filter ,js、css、image等静态资源不被拦截解决方案
- 命令行导出数据mysql数据库_MySQL命令行导出数据库
- UML:图的分类及作用(共5类图,有9种图形)
- 小米电视双十一大降价:55寸仅1399元
- mysql 查询之聚合查询
- word2016取消首字母大写 带图详细讲解
- shell编程之正则表达式与文本工具
- 安装mysql中error nr.1045_win10系统安装mysql提示error Nr.1045如何解决
- Microsoft Dynamics 365咨询服务研究报告-Microsoft Dynamics 365咨询服务生产基地、总部、竞争对手及市场地位
- 超级棒的手机流量管理软件,节约流量有技巧
- 【Sass/SCSS】预加载器中的“轩辕剑”
- 深入浅析Service Workers
- C#操纵Word的坑
- 逻辑回归(logistic regression)原理理解+matlab实现
- 全栈工程师必备技能栈,聊聊月薪2W以内都该会点啥?
- 【有奖测评】我的产品你来反馈,有奖
- 开机、重启和用户登录注销
- JQuery之常用插件
- 那些长期喝咖啡的人,现在都怎么样了?