本周项目为:
编写myls程序,在命令行界面实现ls的基本功能。
基本需求:
- 实现ls -a
- 实现ls -l
- 实现ls -R
- 实现上述三种功能混合查找
- 界面需要美观(对齐等格式要处理好)
此项目运用大量linux文件操作,我相关知识的学习也是基于《Linux C 编程实战》第六章内容。
功能分析:
分析ls函数拥有哪些功能。
首先,看一下ls:
ls [-alrtAFR] [name...]
被用以显示目录内容。
不只是文件的完整地址,在ls -l的功能中,我们需要显示出每个文件的类型、权限、大小等等,因此要借助struct stat buf
,通过完整的地址 pathname
来获取文件信息。鉴于lstat
函数返回的是符号链接文件本身的信息,这里使用语句
lstat(pathname,&buf)
,同时可以通过其返回值是否为-1,判断文件属性是否获取成功。
此外,也会需要DIR
、struct dirent
类型的指针来获取文件属性信息,使用方法不在此赘述。
第二点,是ls 不带-l
时产生的“输出对齐”问题。从第一张图中可以看到,我们需要把所有文件排序后,按行列对齐的格式输出。原程序使用的是竖列打印的方式,但是对于我来说过于复杂,难以用程序控制,所以在myls中,我选择的是横排顺序输出的方法,如下图。
实际操作起来也比较简单:设定全局变量为一行的输出最长长度#define LMAX 100
和当前输出行剩余长度int l_leave=LMAX
,并在之前判断需打印的最长文件名长度int l_max
。使每行打印LMAX / l_max
个文件名,并用格式化输出使其对其即可。
第三点就是稍微复杂一点的-R功能了。其原理比较好解释,就是在调用分析函数时,运用递归的思想,当当前文件类型为目录时,进入它,并再次调用函数。
函数实现
我们需要在命令行形式下调用myls,所以和以前的简单函数不同,需要判断main函数的参数。
因为myls支持输入文件名或者不完全的相对地址,我们需要在最初分析参数path
时,在前面加上‘ . / ’,后面补齐‘ / ’。
strcpy(path,"./");
if(S_ISDIR(buf.st_mode))//是目录
{
if(path[nn-1]!='/')
strcat(path,"/");
strcat(path,"\0");
...
}
需要注意的是,此类功能板块较多的函数,很容易因为一处疏忽而报错误。因此我按照书本的示例写了一个my_err
函数,对不同位置不同问题的函数进行报错。我在源代码中也有很多注释,方便我在后续引用函数或代码块时能快速理解。
void my_err(const char* errnotice,int line)
{
fprintf(stderr,"line:%d",line);
perror(errnotice);
exit(1);
}
我的三大类标示注释: