whyisyoung's Blog

If you can not persist, you will never succeed :)

Linux Command "Ls" Simple Implementation

| Comments

source code: github # multiple files

unix v7 ls.c: code

功能

1. 支持五个参数选项,支持混合使用(如 -traRl )

  • -t – 按照文件修改时间排序
  • -r – 逆序输出
  • -a – 不隐藏 . 开头的文件
  • -R – 递归输出子目录的文件
  • -l – 按行输出详细文件信息

2. 默认分栏输出, 默认按文件名排序 (大小写不敏感)

#### 3. 支持指定一个或多个目录, 目录和参数选项不分先后顺序 * myls ~ * myls ~ .. * myls -atl . ~

4. 颜色支持

目录用蓝色标出, 其余文件用绿色标出

HOW

#### 1. 总体思路

  • 写之前拜读了一下 linux kernel coding style, tab的宽度设为8位也是由此而来。 另外基本上每行代码都不超过80 列。

  • 总的来说就是先存取文件名和文件信息到结构体中,然后根据不同的参数选项输出不同的信息。

    具体一点: 将文件的 nameinfo 保存在一个结构体 FileList 中,如果没有 -a 的参数, 就不收集 . 开头的文件。默认按字典序排序,若有 -t 选项则按文件的修改时间排序(新文件在前), 若有 -r 选项则将结构体中存取的信息颠倒一下。 到输出的时候,若有 -R 选项则递归输出子目录下的信息,否则若有 -l 选项则输出详细信息。

2. 参数的处理

一开始打算手工处理,后来经Halftan提示使用了<unistd.h> 中的 getopt() 函数处理命令行选项,它是一个专门设计来减轻命令行处理负担的库函数。你可以查看IBM developerWorks的一篇博文:使用 getopt() 进行命令行处理

除了支持混合使用参数外,对于参数的扩展支持也是比较好的,只要修改 全局变量 char *optString ,并在main函数里加入选项即可。

3. 输出的处理

  • 分栏

    分栏实现地比较简单,效果基本满足要求吧,先获得所有文件名的最大长度,再获得终端的列数,将列数除以 (最大长度 +1 )作为分的栏数。

  • 递归输出

    递归主要就是先输出 该目录 下的文件(判断是否有 -l调用不同的 display 函数 ), 然后遍历该目录,若文件是一个目录的话,重新获得 目录名,将子目录的文件保存到一个新的 FileList 结构体数组, 递归调用该函数本身(注意此处 ... 都是一个目录, 否则将进入死循环

  • 颜色支持

    本以为颜色的支持比较难,google了一下bash color code 还是比较简单的,只要修改 printf 函数就好了。基本的格式是 \e[34m , 其中 34 代表的是蓝色。你可以在这里获取其他颜色的表示:终端颜色显示

Bug

未使用 malloc 动态分配结构体数组,导致了处理长文件名时的一些错误。(可能文件名长度超过 80 就会报错了)

另外分栏输出在处理中文目录时显得很捉急,正确的方法可以参考Halftan神的代码:myls.c

总结

对于 linux 编程还是太生疏了, man 用的还不是那么熟练,那天装了个 manpages-dev,好用很多。

Comments