今天我们要讨论的是bash shell的一个重要命令,就是“ls”命令。Linux 中的 ls 命令是每个 Linux 用户都应该知道的最重要的命令之一。如果您是使用命令行的初学者,ls 可能是您应该尝试学习的第一个命令。

ls 是 list 的缩写,用于列出当前工作目录或其他目录(如果指定)中的文件。

ls命令为什么这么重要

ls 如此重要的原因在于它允许查看目录中的文件。将经常使用它来列出目录内容。 ls 不是一个复杂的命令,实现起来也很容易,但它确实包含许多不同的选项,可用于列出包含附加信息的文件。

在这过程中,你可能会发现其中一些选项非常有用,即使 ls 本身总是足以列出内容。掌握 ls 命令将使你更有效地列出目录内容和查找文件。它也可以在 Bash 脚本中使用,以帮助其他工具操作文件。

最后,我们每天在使用linux的时候经常使用 ls 命令,但是你了解ls的实现吗?

快速了解ls命令

ls 命令列出目录中包含的文件和子目录。 您可以与 ls 一起使用的选项主要是为了列出附加信息,或者以不同的方式格式化输出。


ls -l显示文件或目录、大小、修改日期和时间、文件或文件夹名称和文件所有者及其权限。

其他选项这里就不列举出来了,感兴趣的可以通过man手册了解。

怎么实现ls命令?

我们已经通过在命令行上输入ls命令,列出目录中包含的文件和子目录。


-a 选项还将列出隐藏文件(名称以 . 开头的文件)。 除非您在根目录中,否则它还会列出 . (当前工作目录)和 … (向上一个目录)作为文件。

那么我们如何读取目录、文件信息呢?

#include <dirent.h>
struct dirent *readdir(DIR *dirp);

最多常见的readdir使用方式:

#include<stdio.h>
#include<dirent.h>
#include<string.h>
#include <stdio.h>
#include <iostream>
#include <stdlib.h>using namespace std;#define FILE_NAME "/opt/code/linux_command_code"int main(int argc, char **argv)
{DIR   *dir;struct  dirent *ptr;dir = opendir(FILE_NAME);if(NULL == dir){cout << "opendir is NULL" << endl;return -1;}while( (ptr = readdir(dir))!=NULL){printf("d_ino:%ld  d_off:%ld d_name: %s\n", ptr->d_ino,ptr->d_off,ptr->d_name);   }closedir(dir);return 0;
}

编译运行:

上面输出是未按照文件名排序。

readdir函数按照在磁盘的索引顺序,d_off来排序,若是须要按照文件名d_name,须要遍历后将文件名保存,再次排序。

  • scandir 的使用
int scandir(const char *dir,struct dirent **namelist,int (*filter)(const void *b),int ( * compare )( const struct dirent **, const struct dirent ** ) );
int alphasort(const void *a, const void *b);
int versionsort(const void *a, const void *b);

函数scandir扫描dir目录下以及dir子目录下满足filter过滤模式的文件,返回的结果是compare函数经过排序的,并保存在 namelist中。注意namelist是通过malloc动态分配内存的,所以在使用时要注意释放内存。alphasort和versionsort 是使用到的两种排序的函数。

常见scandir的使用:

#include<stdio.h>
#include<dirent.h>
#include<string.h>
#include <stdio.h>
#include <iostream>
#include <stdlib.h>using namespace std;#define FILE_NAME "/opt/code/linux_command_code"int main(int argc, char **argv)
{struct dirent **namelist;int n;n = scandir(FILE_NAME,&namelist,0,alphasort);if(n < 0){ cout << "scandir return "<< n  << endl;}else{int index=0;while(index < n){printf("d_ino:%ld  d_off:%ld d_name: %s\n", namelist[index]->d_ino,namelist[index]->d_off,namelist[index]->d_name);free(namelist[index]);index++;}free(namelist);}return 0;
}

编译运行:

scandir函数中能够直接调用排序函数,将遍历到的文件名按照顺序保存在队列中。

下面我们来看看怎么实现ls -l ;

如何实现 ls -l

在 Linux 中与 ls 命令一起使用的最常用选项之一是 -l。 此选项以更长的格式列出目录内容。

上面输出向我们显示目录中所有文件的文件权限、指向该文件的符号链接数量、每个文件的所有者和组、上次修改时间等。

下面是定义的7个字段。

char *   getperm (char * , struct stat filestat);
int     getlinks(struct stat filestat);
char *  getuser (struct stat filestat);
char *  getgroup(struct stat filestat);
int getsize (struct stat filestat);
char *  getdate (char * , struct stat filestat);
char *  getname (char * , char * , char , int);

获得文件信息

stat 能获取与文件系统及文件相关的许多信息,具体用途见stat的功能选项。这些信息包括inode、atime、ctime、mtime、文件(系统)类型、权限、块大小、符号连接等。

下面我来实现 ls -l,具体代码如下:

#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
#include <locale.h>
#include <langinfo.h>
#include <stdio.h>
#include <stdint.h>
#include <iostream>
#include <stdlib.h>using namespace std;#define FILE_NAME "/opt/code/linux_command_code/ls/stat_test"
char * getperm(char * perm , struct stat fileStat);int main(int argc , char * argv[])
{DIR   *dir;struct dirent  *dp;struct stat     statbuf;struct passwd  *pwd;struct group   *grp;struct tm      *tm;char            datestring[256];char modestr[11];dir = opendir(FILE_NAME);if(NULL == dir){cout << "opendir is NULL" << endl;return -1;}/* 循环遍历目录条目 */while ((dp = readdir(dir)) != NULL) {/* 获取条目信息  */if (stat(dp->d_name, &statbuf) == -1)continue;/* 打印出链接的类型、权限和数量*/printf("%10.10s", getperm(modestr,statbuf));printf("%4d", statbuf.st_nlink);/* 如果使用 getpwuid() 找到所有者的名称,则打印出所有者的名称。  */if ((pwd = getpwuid(statbuf.st_uid)) != NULL)printf(" %-8.8s", pwd->pw_name);elseprintf(" %-8d", statbuf.st_uid);/* 如果使用 getgrgid() 找到组名,则打印出组名。 */if ((grp = getgrgid(statbuf.st_gid)) != NULL)printf(" %-8.8s", grp->gr_name);elseprintf(" %-8d", statbuf.st_gid);/* 打印文件的大小。  */printf(" %9jd", (intmax_t)statbuf.st_size);tm = localtime(&statbuf.st_mtime);/* 获取本地化的日期字符串。 */strftime(datestring, sizeof(datestring), nl_langinfo(D_T_FMT), tm);printf(" %s %s\n", datestring, dp->d_name);}  return 0;
}char * getperm(char * perm , struct stat fileStat) {if ( S_ISLNK(fileStat.st_mode) ) {perm[0] = 'l';}else if ( S_ISDIR(fileStat.st_mode) ) {perm[0] = 'd';}else if ( S_ISCHR(fileStat.st_mode) ) {perm[0] = 'c';}else if ( S_ISSOCK(fileStat.st_mode) ) {perm[0] = 's';}else if ( S_ISFIFO(fileStat.st_mode) ) {perm[0] = 'p';}else if ( S_ISBLK(fileStat.st_mode) ) {perm[0] = 'b';}else {perm[0] = '-';}perm[1] = ((fileStat.st_mode & S_IRUSR) ? 'r' : '-');perm[2] = ((fileStat.st_mode & S_IWUSR) ? 'w' : '-');perm[3] = ((fileStat.st_mode & S_IXUSR) ? 'x' : '-');perm[4] = ((fileStat.st_mode & S_IRGRP) ? 'r' : '-');perm[5] = ((fileStat.st_mode & S_IWGRP) ? 'w' : '-');perm[6] = ((fileStat.st_mode & S_IXGRP) ? 'x' : '-');perm[7] = ((fileStat.st_mode & S_IROTH) ? 'r' : '-');perm[8] = ((fileStat.st_mode & S_IWOTH) ? 'w' : '-');perm[9] = ((fileStat.st_mode & S_IXOTH) ? 'x' : '-');if ( fileStat.st_mode & S_ISUID ) {perm[3] = 's';}else if ( fileStat.st_mode & S_IXUSR ) {perm[3] = 'x';}else {perm[3] = '-';}if ( fileStat.st_mode & S_ISGID ) {perm[6] = 's';}else if ( fileStat.st_mode & S_IXGRP ) {perm[6] = 'x';}else {perm[6] = '-';}if ( fileStat.st_mode & S_ISVTX ) {perm[9] = 't';}else if ( fileStat.st_mode & S_IXOTH ) {perm[9] = 'x';}else {perm[9] = '-';}perm[10] = 0;return perm;
}

编译运行:

  • 权限

针对文件:r-查看,w-修改,x-执行
针对文件夹:r-列出文件夹下的所有文件和文件夹,w-在目录中创建和删除,x-进入目录

权限数字说明:权限字母组合转换为二进制1,0组合,有字母的位用1表示,-的位用0表示,然后转换为十进制数字。如:

rwx组合对应的二进制为 111,转换为十进制7
rw-组合对应的二进制为 110,转换为十进制6
r-x组合对应的二进制为 101,转换为十进制5

在struct stat中,文件所有者都是以ID形式存在的,代码中输出用户名和组名。主要使用了该函数:

char * getuser(struct stat fileStat)
{struct passwd *pass = getpwuid(fileStat.st_uid);return pass->pw_name;
}char * getgroup(struct stat fileStat)
{struct group *pass = getgrgid(fileStat.st_gid);return pass->gr_name;
}

总的来说,实现“ls -l”功能所涉及的特殊结构体较多,基础知识考察较多,需要注意细节。逻辑结构上算是很简单,没有什么需要特别留意的地方。

ls命令具体选项实现

使用 -t 选项按修改时间对文件进行排序。 这会将最近编辑的文件带到输出的顶部,使它们更容易找到。


使用 -R 选项递归列出目录的内容。 这意味着每个子目录的内容也将被列出。

int main(int argc , char * argv[]) {char c = 0;char ** arg = NULL;int count_arg = 0;options_t * opt = (options_t *) calloc(1 , sizeof(options_t));while ( (c = getopt(argc, argv, "aSdltR")) != -1) {switch (c) {case 'a':opt->flag_a = 1;break;case 'S':opt->flag_S = 1;opt->flag_t = 0;break;case 'd':opt->flag_d = 1;break;case 'l':opt->flag_l = 1;break;case 't':opt->flag_t = 1;opt->flag_S = 0;break;case 'R':opt->flag_R = 1;break;case '?':break;default:printf ("?? getopt returned character code 0%o ??\n", c);}}if (optind < argc) {arg = (char **) calloc ( (argc - optind) , sizeof(char *) );count_arg = 0;while (optind < argc) {arg[count_arg++] = argv[optind++];}}ls(opt , arg , count_arg);if( arg != NULL )free( arg );free(opt);return 0;}

编译运行

总结

在 Unix/Linux 的文件系统中,所有东西的储存形式都是文件(一切皆文件的理念)。ls命令是linux下最常用的命令之一,它的使用很简单,可是功能却很多,有很多的参数,本篇文章中给出了一些测试例子,方便理解ls命令。

欢迎关注微信公众号【程序猿编码】,需要ls命令源码的添加本人微信号(c17865354792)

Linux c/c++下ls命令的实现(超详细)相关推荐

  1. Linux下 ls 命令的高级用法8例

    Linux下 ls 命令的高级用法8例 在Linux下,ls这个命令大家肯定太熟悉了,良许相信只要是Linux工程师,每天都会离不开这个命令,而且一天会使用个几百次.但是,除了 ls -l 以外,你还 ...

  2. Linux 和uboot下dd命令读写sd,mmc,mm读写内存命令

    Linux 和uboot下dd命令读写sd,mmc名,mm读写内存命令,记录一下,后面写

  3. 【Linux】centOS 使用ls命令能显示出来文件夹用cd命令却进不去?

    [Linux]centOS 使用ls命令能显示出来文件夹用cd命令却进不去? 方法一:可以使用反斜杠

  4. centos7修改ip地址命令_每天一条Linux命令(12) hostnam (超详细)

    在Linux系统中,命令 hostname 用于显示或者设置系统主机名称.许多网络程序均用主机名来标识主机,若没有设置好主机名,则可能会导致网络服务不正常. 语法: hostname [选择] 参数: ...

  5. Windows10系统下配置mmdetection2.6(超详细)

    Windows10系统下配置mmdetection2.6(超详细) 因为最近参加目标检测的比赛,选择Varifocalnet做训练论文链接,代码链接,这个模型需要在mmdetection上配置,这篇博 ...

  6. 嵌入式:Keil uvision5环境下创建一个工程模板(步骤超详细)

    嵌入式:Keil uvision5环境下创建一个工程模板(步骤超详细) 1.创建一个空的文件夹,命名为"test"(可以为任何名字) 2.打开test文件夹,在该目录下依次创建两个 ...

  7. 8 个 Linux 下 ls 命令的高级用法!个个惊艳!

    作者 | 良许 责编 | 胡巍巍 在Linux下,ls这个命令大家肯定太熟悉了,笔者相信只要是Linux工程师,每天都会离不开这个命令,而且一天会使用个几百次. 但是,除了ls -l以外,你还知ls的 ...

  8. 实现linux下 ls命令 (-a,-l,-R,-r,-i)

    ls各个命令的功能 -a : 显示所有文件,连同隐藏文件一起列出来 -l : 一行只显示一个文件的详细信息 -R: 递归输出文件 -r : 逆序输出文件名 -i : 输出文件的 i 节点的索引信息 遇 ...

  9. linux下ls命令和dir命令的区别

    linux下ls和dir命令的作用相同,都是列出目录内容的命令. 区别如下: ls:会显示不同类型的文件的颜色 dir:不显示不同文件类型的文件颜色,所有文件都是一种颜色. 由此可见,虽然ls和dir ...

最新文章

  1. 常用组策略故障排除工具
  2. RSA算法原理——(1)目前常见加密算法简介
  3. php建站静态,php网站如何生成静态
  4. inputstreamreader未关闭会导致oom_Linux内核OOM机制分析和防止进程被OOM杀死的方法...
  5. oracle 慕课课程_我在慕课网学习到的oracle
  6. Bailian4041 矩阵运算【数学计算】
  7. jts116_JTS T 116-2019水运建设工程概算预算编制规定.pdf
  8. Opencv使用cv::matchTemplate进行模板匹配
  9. python输出10行带标号的hello、world_Python输出hello world(各行命令详解)
  10. JVM 字节码指令手册 - 查看 Java 字节码
  11. excel熵值法计算权重_由搜索权重排序引入的思考
  12. android9系统WIFI提示已连接,无法访问互联网
  13. 简单实用算法——人民币金额大写转换
  14. C语言数组——一维数组实例详解
  15. 运营能力提升学习(一)了解运营是什么
  16. iOS 动画之翻页动画实现
  17. 如何搭建易企秀H5平台?
  18. 工控安全与传统安全区别
  19. python 遍历列表中的每个元素 for循环 while循环 迭代器
  20. 18000-6C整理-入门query/CRC-5

热门文章

  1. JavaSE第一阶段知识概括
  2. 你了解Simulation中不同单元有何区别吗?
  3. modelsim仿真一直卡在loading的解决办法
  4. webgl与opengl的区别和联系
  5. daysmatter安卓版_days matter最新版下载-Days Matter倒数日软件下载v2.2.1 安卓版-单机手游网...
  6. 计算机处理器技术类毕业论文文献都有哪些?
  7. 老黄历java_基于聚合数据的老黄历接口调用示例-JAVA版
  8. cmd中复制粘贴切换命令
  9. 完美解决win10可选更新后,usb外接键盘失灵的问题
  10. Bundle的使用示例