使用linux c 实现linux控制台 ls 命令
2016-07-20 13:35
567 查看
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <error.h> #include <time.h>// ctime()函数 #include <dirent.h>//操作目录 #include <sys/stat.h>//操作文件 #include <pwd.h>// 获取文件所有者 #include <grp.h> //InfoModeAll -a InfoModeDetail -l //显示信息模式 typedef enum _InfoMode { InfoModeBothNo,InfoModeAll,InfoModeDetail,InfoModeBoth} InfoMode; //目录元素种类(文件、目录) enum ItemCategory { ItemCategoryDir, ItemCategoryFile }; //显示目录中元素列表 void display_dirItemList(char *path, int isAll); //显示目录中元素信息 void display_dirItemInfo(char *path, int isAll); //显示目录信息 void display_singleDirInfo(char *path); //显示文件信息 void display_singleFileInfo(char *path); //显示文件名,根据文件路径 void display_fileName(char *path); //显示文件信息 void display_fileInfo(char *path, InfoMode mode); //显示目录信息 void display_dirInfo(char *path, InfoMode mode); //解析命令行参数,返回,显示信息模式 InfoMode AnalyticalParm(int argc, char **arg); //获取完整路径 void getAbsolutePath(char *path); //检查path是否为绝对路径,0 不是,是相对路径 1 是绝对路径 int checkPathIsAbsolutePath(char *path); //获取目录下的文件/目录名称,返回char **(这个变量需要动态释放),以及fileNameCount void getFileNameListFormDir(char *path,int isAll,char fileNameList[][10],int *fileNameCount); //打印目录元素的属性 void Demonstrate_attribute(struct stat buf); //判断元素是文件还是目录 int checkPathIsFile(char *path); int main(int argc, char **arg) { /* argc = 3; arg[0] = "./my_ls"; arg[1] = "-a"; arg[1] = "-l"; arg[2] = "/home/pengjing/文档/10-文件读写/my_ls/bin/Debug/test/"; //int i; //for(i=0; i<argc; i++) { //printf("%s\t",arg[i]); //} //printf("\n"); */ InfoMode mode = AnalyticalParm(argc, arg); char *path = arg[argc-1]; //判断是否为文件名,还是目录名,当res_index为0时,是目录名,当res_index为.所在的索引时为文件名 getAbsolutePath(path); //过滤最后一个"/" if(path[strlen(path)-1] == '/'){ path[strlen(path)-1] = '\0'; } int isFile = checkPathIsFile(path); if(isFile == 1) { display_fileInfo(path,mode); } else { display_dirInfo(path,mode); } return 0; } void display_dirItemList(char *path, int isAll) { int fileNameCount = 0; char fileNames[30][10]; getFileNameListFormDir(path,isAll,fileNames,&fileNameCount); int i; for(i=0;i<fileNameCount;i++){ printf("%-s\t",fileNames[i]); } printf("\n"); } void display_dirItemInfo(char *path, int isAll) { int fileNameCount = 0; char fileNameList[30][10]; char filePathList[30][100]; int i,j; getFileNameListFormDir(path,isAll,fileNameList,&fileNameCount); for(i=0; i<fileNameCount; ++i) { char filePath[90] = {'\0'}; strcpy(filePath,path); strcat(filePath,"/"); strcat(filePath,fileNameList[i]); strcpy(filePathList[i],filePath); } struct stat _stat; for(i=0; i<fileNameCount; i++) { //bzero(_stat,sizeof(struct stat)); //printf("%s\n",filePathList[i]); // /home/pengjing/document/10-文件读写/my_ls/bin/Debug/test/file1 // char *myPath = "/home/pengjing/document/10-文件读写/my_ls/bin/Debug/test/file1"; int res_lstat = lstat(filePathList[i],&_stat); if(res_lstat == -1) { perror("lstat"); exit(0); } Demonstrate_attribute(_stat); } } void getFileNameListFormDir(char *path,int isAll,char fileNameList[][10],int *fileNameCount) { struct dirent *diren; DIR *dir; *fileNameCount = 0; //printf("fileNameList size :%ld\n",sizeof(fileNameList)); if((dir = opendir(path)) == NULL) { perror("opendir"); } while((diren = readdir(dir)) != NULL) { char *name = diren->d_name; if(isAll == 0 && name[0] == '.') { continue; } strcpy(fileNameList[*fileNameCount],name); (*fileNameCount)++; } closedir(dir); } //显示文件信息 void display_singleFileInfo(char *path) { //printf("显示单个文件信息\n"); struct stat _stat; int res_lstat = lstat(path,&_stat); if(res_lstat == -1) { perror("lstat"); exit(0); } Demonstrate_attribute(_stat); } void display_fileName(char *path){ //printf("显示文件名"); char res[10],*a; a = rindex(path,'/'); strcpy(res,a); int i; for(i=1;i<strlen(res);i++){ res[i-1] = res[i]; } res[i-1] = '\0'; printf("%s\n",res); } //显示文件信息 void display_fileInfo(char *path, InfoMode mode) { //printf("显示文件的详细信息 mode:%d\n",mode); //根据显示模式显示内容 switch(mode) { case InfoModeBothNo: { //显示目录中元素的名称 display_fileName(path); break; } case InfoModeAll: { //显示目录中所有元素的名称 display_fileName(path); break; } case InfoModeDetail: { //显示目录下元素的信息 display_singleFileInfo(path); break; } case InfoModeBoth: { //显示目录下所有元素的信息 display_singleFileInfo(path); break; } default : { //mode 错误 printf("mode 错误"); exit(0); break; } } } //显示目录信息 void display_dirInfo(char *path, InfoMode mode) { //printf("显示目录的详细信息 mode:%d\n",mode); //根据显示模式显示内容 switch(mode) { case InfoModeBothNo: { //显示目录中元素的名称 display_dirItemList(path,0); break; } case InfoModeAll: { //显示目录中所有元素的名称 display_dirItemList(path,1); break; } case InfoModeDetail: { //显示目录下元素的信息 display_dirItemInfo(path,0); break; } case InfoModeBoth: { //显示目录下所有元素的信息 display_dirItemInfo(path,1); break; } default : { //mode 错误 printf("mode 错误"); exit(0); break; } } } //解析命令行参数,返回parmCount(参数个数),显示信息模式 InfoMode AnalyticalParm(int argc, char **arg) { int i; InfoMode mode = InfoModeBothNo; for(i = 1 ; i < argc; i++) { if(arg[i][0] == '-') { if(arg[i][1] == 'a') { if(mode == InfoModeDetail) { mode = InfoModeBoth; break; } mode = InfoModeAll; } else if(arg[i][1] == 'l') { if(mode == InfoModeAll) { mode = InfoModeBoth; break; } mode = InfoModeDetail; } } } return mode; } int checkPathIsAbsolutePath(char *path) { int res = 0; if(path[0] == '/' || path[0] == '~') { res = 1; } return res; } //获取文件属性并打印 void Demonstrate_attribute(struct stat buf){ char buf_time[32]; //存放时间 struct passwd *psd; //从该结构体中获取文件所有者的用户名 struct group *grp; //从该结构体中获取文件所有者所属组的组名 /* 我们使用最多的属性是st_mode.通过着属性我们可以判断给定的文件是一个普通文件还是一个目录,连接等等.可以使用下面几个宏来判断. S_ISLNK(st_mode):是否是一个连接 S_ISREG是否是一个常规文件 S_ISDIR是否是一个目录 S_ISCHR是否是一个字符设备 S_ISBLK是否是一个块设备 S_ISFIFO是否是一个FIFO文件 S_ISSOCK是否是一个SOCKET文件 S_IFMT 0170000 文件类型的位遮罩 S_IFSOCK 0140000 socket S_IFLNK 0120000 符号链接(symbolic link) S_IFREG 0100000 一般文件 S_IFBLK 0060000 区块装置(block device) S_IFDIR 0040000 目录 S_IFCHR 0020000 字符装置(character device) S_IFIFO 0010000 先进先出(fifo) S_ISUID 0004000 文件的(set user-id on execution)位 S_ISGID 0002000 文件的(set group-id on execution)位 S_ISVTX 0001000 文件的sticky位 S_IRWXU 00700 文件所有者的遮罩值(即所有权限值) S_IRUSR 00400 文件所有者具可读取权限 S_IWUSR 00200 文件所有者具可写入权限 S_IXUSR 00100 文件所有者具可执行权限 S_IRWXG 00070 用户组的遮罩值(即所有权限值) S_IRGRP 00040 用户组具可读取权限 S_IWGRP 00020 用户组具可写入权限 S_IXGRP 00010 用户组具可执行权限 S_IRWXO 00007 其他用户的遮罩值(即所有权限值) S_IROTH 00004 其他用户具可读取权限 S_IWOTH 00002 其他用户具可写入权限 S_IXOTH 00001 其他用户具可执行权限 */ //获取并打印文件类型 if (S_ISLNK(buf.st_mode)){ //判断是否为符号链接 printf("l"); }else if (S_ISREG(buf.st_mode)){ //判断是否为文件 printf("-"); }else if (S_ISDIR(buf.st_mode)){ //判断是否为目录 printf("d"); }else if (S_ISCHR(buf.st_mode)){ //判断是否为字符设备文件 printf("c"); }else if (S_ISBLK(buf.st_mode)){ //判断是否为块设备文件 printf("b"); }else if (S_ISFIFO(buf.st_mode)){ //判断是否为先进先出的FIFO printf("f"); }else if (S_ISSOCK(buf.st_mode)){ //判断是否为socket printf("s"); } //获取并打印文件所有者的权限 //按位与结果作为条件判断,应当判断其与结果为0还是非0数值 当前比较的是buf.st_mode在用户读权限的位与S_IRUSR是否相等 if (buf.st_mode & S_IRUSR){ printf("r"); }else{ printf("-"); } if (buf.st_mode & S_IWUSR){ printf("w"); }else{ printf("-"); } if (buf.st_mode & S_IXUSR){ printf("x"); }else{ printf("-"); } //获取并打印与文件所有者同组的用户对该文件的操作权限 if(buf.st_mode & S_IRGRP){ printf("r"); }else{ printf("-"); } if(buf.st_mode & S_IWGRP){ printf("w"); }else{ printf("-"); } if(buf.st_mode & S_IXGRP){ printf("x"); }else{ printf("-"); } //获取并打印其它用户的对该文件的操作权限 if (buf.st_mode & S_IROTH){ printf("r"); }else{ printf("-"); } if (buf.st_mode & S_IWOTH){ printf("w"); }else{ printf("-"); } if (buf.st_mode & S_IXOTH){ printf("x"); }else{ printf("-"); } printf(" "); //根据uid与gid获取文件所有者的用户名与组名 psd = getpwuid(buf.st_uid); grp = getgrgid(buf.st_gid); printf("%4d ",buf.st_nlink); //打印文件的链接数(该文件硬链接数目) printf("%-9s", psd->pw_name); //打印文件拥有者 printf("%-8s", grp->gr_name); //打印文件所属用户组 printf("%6d",(int)buf.st_size); // 打印文件的大小 char *wo = ctime(&buf.st_mtime); strcpy(buf_time, ctime(&buf.st_mtime)); buf_time[strlen(buf_time) - 1] = '\0'; // 去掉换行符 printf(" %s\n", buf_time); // 打印文件的时间信息 } int checkPathIsFile(char *path){ int res = 0; struct stat _stat; int res_lstat = lstat(path,&_stat); if(res_lstat == -1){ perror("lstat"); exit(0); } if(S_ISREG(_stat.st_mode)){ //判断是否为文件 res = 1; } return res; } void getAbsolutePath(char *path){ //组建绝对路径 char absPath[100]; int isAbsolutePath = checkPathIsAbsolutePath(path); if(isAbsolutePath == 1) { //absPath = (char *)malloc(sizeof(char) * strlen(path)); strcpy(absPath,path); } else { if(getcwd(absPath,200) == NULL) { perror("获取当前工作目录失败"); } strcat(absPath,"/"); strcat(absPath,path); //printf("absPath:%s\n",absPath); } path = absPath; }
相关文章推荐
- Linux socket 初步
- Linux Kernel 4.0 RC5 发布!
- linux lsof详解
- linux 文件权限
- Linux 执行数学运算
- 10 篇对初学者和专家都有用的 Linux 命令教程
- Linux 与 Windows 对UNICODE 的处理方式
- Ubuntu12.04下QQ完美走起啊!走起啊!有木有啊!
- 解決Linux下Android开发真机调试设备不被识别问题
- 运维入门
- 运维提升
- Linux 自检和 SystemTap
- Ubuntu Linux使用体验
- c语言实现hashmap(转载)
- Linux 信号signal处理机制
- linux下mysql添加用户
- Scientific Linux 5.5 图形安装教程
- Linux 下无损图片压缩小工具介绍