linux下使用c语言模拟ls [-l] [路径名] 命令
2017-12-09 19:28
148 查看
同样是一个作业,这比前一个linux下使用c语言模拟tail [-n] 命令要难一些了。
但是既然是作业,再麻烦也还是要做的,网上搜到的都是200多行甚至300多行的代码,还没有详细说明,既不想直接copy,也不想去看懂300来行几乎没注释的代码,所以就自己来了。
不借鉴别人是不可能的,于是我发现了一篇文章linux下用c实现ls命令 ,这是我找到的最简洁的一篇文章了,代码可以直接copy过来,如下:
但是显然没有达到我所要的要求,我还需要模拟ls -l 以及自定义目录呀,这篇博客里写的只能显示当前目录下所有文件或者文件夹等的名称,而且输出的排版也有点凌乱。
看完代码后,当即就发现他是使用一个定义在头文件中的结构体来实现的,那么这个结构体会不会也包含别的信息呢,比如包括了权限信息、组id、最近操作时间等等的。
我向来是不惮以最好的想法来揣测编写头文件的大佬的,然而我还不料,也不信竟让我失望到如此地步
结构体 dirent 的结构如下,从百度百科copy来的:
这下傻眼了,感情
不要急着去看,除了有目录固定,格式固定等的局限性外,还有错误。
我的代码实质上就是将他的两篇博文的功能合并了,然后允许自定义目录,也改掉了他的bug。
先说下这位博主的错误:
1、其在通过文件名获取文件细节信息时所用语句为
2、上述错误可以说是这位博主没有考虑到的地方,因为其并未判断文件是否为软链接,因此在
而该文章中我一处不明白的就在:
下面就放我的完整代码吧,linux虚拟机里没装中文输入法,注释用英文写了:
但是既然是作业,再麻烦也还是要做的,网上搜到的都是200多行甚至300多行的代码,还没有详细说明,既不想直接copy,也不想去看懂300来行几乎没注释的代码,所以就自己来了。
不借鉴别人是不可能的,于是我发现了一篇文章linux下用c实现ls命令 ,这是我找到的最简洁的一篇文章了,代码可以直接copy过来,如下:
#include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <sys/stat.h> #include <dirent.h> #include <string.h> int main(int argc,char* argv[]) { DIR* dir = opendir("."); struct dirent* ent=NULL; while((ent = readdir(dir))) { if((ent->d_type == 4||ent->d_type == 8)&&ent->d_name[0]!='.') printf("%s ",ent->d_name); } closedir(dir); puts(""); return 0; }
但是显然没有达到我所要的要求,我还需要模拟ls -l 以及自定义目录呀,这篇博客里写的只能显示当前目录下所有文件或者文件夹等的名称,而且输出的排版也有点凌乱。
看完代码后,当即就发现他是使用一个定义在头文件中的结构体来实现的,那么这个结构体会不会也包含别的信息呢,比如包括了权限信息、组id、最近操作时间等等的。
我向来是不惮以最好的想法来揣测编写头文件的大佬的,然而我还不料,也不信竟让我失望到如此地步
结构体 dirent 的结构如下,从百度百科copy来的:
struct dirent { long d_ino; /* inode number 索引节点号 */ off_t d_off; /* offset to this dirent 在目录文件中的偏移 */ unsigned short d_reclen; /* length of this d_name 文件名长 */ unsigned char d_type; /* the type of d_name 文件类型 */ char d_name [NAME_MAX+1]; /* file name (null-terminated) 文件名,最长256字符 */ }
这下傻眼了,感情
ls -l和这个没搭边。然后我再去看了上面博主的文章,突然在下面发现了原来这位仁兄还写了另一篇:linux 下用 c 实现 ls -l 命令
不要急着去看,除了有目录固定,格式固定等的局限性外,还有错误。
我的代码实质上就是将他的两篇博文的功能合并了,然后允许自定义目录,也改掉了他的bug。
先说下这位博主的错误:
1、其在通过文件名获取文件细节信息时所用语句为
stat( filename, &info ),但是这个函数是判断不出一个文件是不是软链接的,而在
ls -l中,如果是软链接,显示中会在软链接的名称后加上
->所指向的地址,觉得抽象的去试一下就知道了。因而需要改成
lstat( filename, &info ),就是将stat改成lstat。
2、上述错误可以说是这位博主没有考虑到的地方,因为其并未判断文件是否为软链接,因此在
mode_to_letters()函数中,应该加上
if( S_ISLNK(mode) ) str[0] = 'l';
而该文章中我一处不明白的就在:
printf("%.12s ", 4 + ctime(&info_p->st_mtime));,这条语句写了
4+不知道是为什么,但是加上和不加的时候样式有区别,如果有大佬知道望告知。
下面就放我的完整代码吧,linux虚拟机里没装中文输入法,注释用英文写了:
#include<stdio.h> #include<unistd.h> #include<dirent.h> #include<sys/stat.h> #include<string.h> #include<pwd.h> #include<grp.h> int main(int argc,char **argv) { char c; char *path = "."; int isL = 0; //if have -l,set isL=1,or isL=0 while((c=getopt(argc,argv,"l"))!=-1) { isL = 1; } //printf("%d:%d",argc,optind); if(argc > optind) { path = argv[optind]; } //printf("%s",path); struct dirent* ent = NULL; DIR* dir = opendir(path); int newLine = 0; while((ent = readdir(dir))) { if(isL == 0) { if((ent->d_type == 4 || ent->d_type == 8) && ent->d_name[0]!='.') { printf("%-24s",ent->d_name); newLine++; if(newLine % 3 == 0) printf("\n"); } } else { struct stat info; //get directory detail info char temp[80]; strcpy(temp,path); strcat(temp,"/"); strcat(temp,ent->d_name); if(lstat(temp,&info) == -1) { printf("Cannot open the directory:%s",temp); break; } else { if(ent->d_name[0]!='.') { char *uid_to_name(),*ctime(),*gid_to_name(),*filemode(); void mode_to_letters(); char modestr[11]; //transfer mode to letters mode_to_letters(info.st_mode,modestr); printf("%s",modestr); printf("%4d",(int)info.st_nlink); printf("%8s",uid_to_name(info.st_uid)); printf("%8s",gid_to_name(info.st_gid)); printf("%10ld ",(long)info.st_size); printf("%.12s ",4+ctime(&info.st_mtime)); printf("%s",ent->d_name); static char linkPath[1024]; readlink(temp,linkPath,1024); if(S_ISLNK(info.st_mode)) { printf("->%s",linkPath); } printf("\n"); } } } } closedir(dir); puts(""); } void mode_to_letters(int mode,char str[]) { strcpy(str,"----------"); if(S_ISDIR(mode)) str[0] = 'd'; //directory if(S_ISCHR(mode)) str[0] = 'c'; //characteristic if(S_ISBLK(mode)) str[0] = 'b'; //block if(S_ISLNK(mode)) str[0] = 'l'; //link if(mode & S_IRUSR) str[1]= 'r'; if(mode & S_IWUSR) str[2]= 'w'; if(mode & S_IXUSR) str[3]= 'x'; if(mode & S_IRGRP) str[4]= 'r'; if(mode & S_IWGRP) str[5]= 'w'; if(mode & S_IXGRP) str[6]= 'x'; if(mode & S_IROTH) str[7]= 'r'; if(mode & S_IWOTH) str[8]= 'w'; if(mode & S_IXOTH) str[9]= 'x'; } char *uid_to_name(uid_t uid) { struct passwd *getpwuid(),*pw_ptr; static char numstr[10]; if((pw_ptr = getpwuid(uid)) == NULL) { sprintf(numstr,"%d",uid); return numstr; } return pw_ptr->pw_name; } char *gid_to_name(gid_t gid) { struct group *getgrgid(),*grp_ptr; static char numstr[10]; if((grp_ptr = getgrgid(gid)) == NULL) { sprintf(numstr,"%d",gid); return numstr; } return grp_ptr->gr_name; }
相关文章推荐
- linux下使用c语言模拟tail [-n] 命令
- 【Linux】嵌入式开发,在Linux中使用C语言对Fork函数执行子函数及父函数,命令ps 及 ls 操作
- statfs获得硬盘使用情况 模拟linux命令 df
- Linux下 使用C语言编写who命令
- 做linux第四次实验,看错实验要求,花了一个下午自己模拟着实现一个ls命令。。。。
- linux中如何使用ls命令查看s开头的文件?
- statfs获得硬盘使用情况 模拟linux命令 df
- Linux下 使用C语言编写who命令
- linux中的一些基础命令的使用(which,whereis,locate,find,alias,file,ls,cat,echo,tar,bzip2,gzip,history,mv,cp,rm)
- 模拟linux下的ls -l命令
- Linux中的ls命令详细使用
- linux中ls命令使用详解
- Linux中的ls命令详细使用
- statfs获得硬盘使用情况 模拟linux命令 df
- statfs获得磁盘使用情况 模拟linux命令 打印比较
- Linux的ls命令参数使用大全
- 关于 Linux 的配置文件 /etc/profile 路径出错后相关的命令失效解决方式(如:ls,vi不能用)
- linux使用ls -l命令卡死问题
- linux 的 ls 命令的使用方法
- Linux中的ls命令详细使用