需求分析

ls -l 的使用方式

ls -l 的基本使用方式有两种,分别是ls -l +文件名、ls -l +目录,如下图所示:

根据图片中得到的结果分析出,ls -l 命令得到的结果包含有文件类型,权限信息,链接数,用户名,组名,文件大小,最后修改时间,文件名称以及链接文件的目标文件。 

        故程序的设计要求就是通过用户传入一个文件名或者路径,解析出该文件或者该路径下所有文件的相关信息并按照格式打印到终端上。

功能实现

目录流

打开目录

#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);
{
功能:打开一个目录;
参数:目录名称
返回值: 成功返回一个目录流指针,失败返回NULL;
}

读取目录

#include <dirent.h>
struct dirent *readdir(DIR *dirp);
{
功能:读取目录里面的文件信息;
参数:
dirp:目录流
返回值:成功返回下一个目录项, 失败或者读到目录的末尾返回
NULL,并设置错误号;
}

目录流的关闭

#include <sys/types.h>
#include <dirent.h>
int closedir(DIR *dirp);
返回值:成功返回0, 失败返回-1,并设置错误号;

获取文件的属性

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;     //文件内容对应的块数量};
int stat(const char *pathname, struct stat *statbuf);
如果获取的文件是符号链接文件,那么获取的是符号链接文件的目标的相
关属性
int fstat(int fd, struct stat *statbuf);
以文件描述符的方式来获取文件的属性
int lstat(const char *pathname, struct stat *statbuf);
如果获取的文件是符号链接文件,那么获取的是符号链接文件的本身的相
关属性
返回值:成功返回0, 失败返回-1并设置错误号;

定义一个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);

链接文件的目标文件

        通过ssize_t readlink(const char *pathname, char *buf, size_t bufsiz)函数获取链接文件的目标文件
//链接指向目标文件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 的功能相关推荐

  1. Linux下ll命令与ls -l

    还大三Linux课的债. 1.ll命令用于显示当前文件下非隐藏文件的详情 查询结果分为7栏: 1)如' -rw-r--r--' 表示三种用户对该文件的不同权限: r:可读:w:可写:x:可执行 其中第 ...

  2. Linux下C程序的编辑,编译和运行以及调试

                                                                                                        ...

  3. linux 跟踪程序执行过程,用pvtrace和Graphviz实现对linux下C程序的函数调用跟踪

    用pvtrace和Graphviz实现对linux下C程序的函数调用跟踪 用pvtrace和Graphviz实现对linux下C程序的函数调用跟踪 1:功能介绍,使用本方法可以实现linux下C应用程 ...

  4. Linux常用命令详解 ls -l命令详解

    Linux常用命令详解 ls -l命令详解 一.ls -l命令显示效果 使用ls -l会产生长列表格式输出,包含了目录中每个文件的更多的信息. 注:蓝色或/表示目录,如果带绿色或*号表示可执行文件. ...

  5. 查看linux文件的权限:ls -l 文件名称

    查看linux文件的权限:ls -l 文件名称 查看linux文件夹的权限:ls -ld 文件夹名称(所在目录) 修改文件及文件夹权限: sudo chmod -(代表类型)×××(所有者)×××(组 ...

  6. qt调用linux 进程,Linux 下qt 程序打包发布(使用linuxdelpoyqt ,shell 脚本)

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/u014746574/article/d ...

  7. Linux 下qt 程序打包发布(使用linuxdelpoyqt ,shell 脚本)

    Linux 下qt 程序打包发布(使用linuxdelpoyqt ,shell 脚本) 转载于:https://www.cnblogs.com/zhehan54/p/9549017.html

  8. linux c++ 程序运行时间,总结UNIX/LINUX下C++程序计时的方法

    前言 良好的计时器可帮助程序开发人员确定程序的性能瓶颈,或对不同算法进行性能比较.但要精确测量程序的运行时间并不容易,因为进程切换.中断.共享的多用户.网络流量.高速缓存访问及转移预测等因素都会对程序 ...

  9. 解决Windows下Arm下Linux下Qt4程序的中文乱码问题

    解决Windows下Arm下Linux下Qt4程序的中文乱码问题 ################################################################### ...

最新文章

  1. 寻找Archie服务器中的文件,Archie服务
  2. js和css被屏蔽了,拦截器 Filter ,js、css、image等静态资源不被拦截解决方案
  3. 命令行导出数据mysql数据库_MySQL命令行导出数据库
  4. UML:图的分类及作用(共5类图,有9种图形)
  5. 小米电视双十一大降价:55寸仅1399元
  6. mysql 查询之聚合查询
  7. word2016取消首字母大写 带图详细讲解
  8. shell编程之正则表达式与文本工具
  9. 安装mysql中error nr.1045_win10系统安装mysql提示error Nr.1045如何解决
  10. Microsoft Dynamics 365咨询服务研究报告-Microsoft Dynamics 365咨询服务生产基地、总部、竞争对手及市场地位
  11. 超级棒的手机流量管理软件,节约流量有技巧
  12. 【Sass/SCSS】预加载器中的“轩辕剑”
  13. 深入浅析Service Workers
  14. C#操纵Word的坑
  15. 逻辑回归(logistic regression)原理理解+matlab实现
  16. 全栈工程师必备技能栈,聊聊月薪2W以内都该会点啥?
  17. 【有奖测评】我的产品你来反馈,有奖
  18. 开机、重启和用户登录注销
  19. JQuery之常用插件
  20. 那些长期喝咖啡的人,现在都怎么样了?

热门文章

  1. 阿里p7架构师带你领略JMM
  2. 如何统一设置或者修改Excel表格中图表样式
  3. python分析红楼梦中人物形象_红楼梦中贾宝玉的人物形象分析
  4. 吃内存狂魔?微信官方工具来了:深度清理缓存
  5. c语言编程TLC2543AD采集,51单片机驱动12位AD转换TLC2543电路图+程序
  6. 细述QQ与TIM的不同之处
  7. 中国首届微博开发者大会
  8. Qt开发的国内外知名软件
  9. html5四季特点,美国一年四季天气特点介绍
  10. at命令不生效 linux_Linux命令之at