ls命令的简单实现
目标:简单的实现ls命令
实现的mic_ls命令主要功能
1.循环遍历目录
2.列出目标目录所有的子目录和文件
3.列出文件的文件权限,所有者,文件大小等详细信息
参数
-r 循环遍历
-a 列出全部文件
-l 列出详细信息(文件类型、权限。。。)
环境
ubuntu 14.04 gcc.real (Ubuntu 4.8.2-19ubuntu1) 4.8.2
代码
新手菜鸟 如有错误 欢迎指正
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<stdbool.h>
#include<dirent.h>
#include<string.h>
#include<sys/stat.h>
#include<pwd.h>
#include<grp.h>
bool show_all=false;
bool show_list=false;
bool show_recursion=false;
void do_ls_r(char *pathname,int depth);
void do_ls(char *pathname);
int judge_dir(char *pathname);
void do_showlist(DIR *dp);
void mode_to_letters(int mode,char str[]);
char *uid_to_name(uid_t uid);
char *gid_to_name(gid_t gid);
int main(int argc,char *argv[])
{
int opt;
while((opt=getopt(argc,argv,"arl"))!=-1){
switch(opt){
case 'a':
show_all=true;
break;
case 'r':
show_recursion=true;
break;
case 'l':
show_list=true;
break;
case '?':
printf("unknow option :%c
",optopt);
exit(1);
}
}
if(show_recursion){
if(argc==optind)
do_ls_r(".",4);
else{
for(;optind<argc;optind++){
if(judge_dir(argv[optind])){
printf("%s:
",argv[optind]);
do_ls_r(argv[optind],4);
}
else{
printf("not a directory!
");
exit(1);
}
}
}
}
else{
if(argc==optind)
do_ls(".");
else{
for(;optind<argc;optind++){
if(judge_dir(argv[optind])){
printf("%s:
",argv[optind]);
do_ls(argv[optind]);
}
else{
printf("not a directory!
");
exit(1);
}
}
}
}
}
int judge_dir(char *pathname)
{
struct stat statbuf;
if((lstat(pathname,&statbuf))<0){
printf("error in lstat!
");
exit(1);
}
if(S_ISDIR(statbuf.st_mode))
return 1;
else
return -1;
}
void do_ls_r(char *pathname,int depth)
{
DIR *dp;
struct dirent *entry;
struct stat statbuf;
if((dp=opendir(pathname))==NULL){
printf("can't open dir:%s
",pathname);
exit(1);
}
chdir(pathname);
while((entry=readdir(dp))!=NULL){
lstat(entry->d_name,&statbuf);
if(S_ISDIR(statbuf.st_mode)){
if(strcmp(".",entry->d_name)==0||strcmp("..",entry->d_name)==0)
continue;
printf("%*s%s/
",depth," ",entry->d_name);
do_ls_r(entry->d_name,depth+4);
}
else
printf("%*s%s
",depth," ",entry->d_name);
}
chdir("..");
closedir(dp);
}
void do_ls(char *pathname)
{
DIR *dp;
struct dirent *entry;
if((dp=opendir(pathname))==NULL){
printf("can't open dir:%s
",pathname);
exit(1);
}
if(show_list){
chdir(pathname);
do_showlist(dp);
}
else{
while((entry=readdir(dp))!=NULL){
if(!show_all)
if(*(entry->d_name)=='.')
continue;
printf("%s
",entry->d_name);
}
closedir(dp);
}
}
void do_showlist(DIR *dp)
{
struct dirent *entry;
struct stat statbuf;
char l_mode[11];
while((entry=readdir(dp))!=NULL){
if((lstat(entry->d_name,&statbuf))<0){
printf("error :in lstat
");
exit(1);
}
if(!show_all)
if(*(entry->d_name)=='.')
continue;
mode_to_letters(statbuf.st_mode,l_mode);
printf("%s",l_mode);
printf("%4d ",(int)statbuf.st_nlink);
printf("%-8s ",uid_to_name(statbuf.st_uid));
printf("%-8s ",gid_to_name(statbuf.st_gid));
printf("%8ld ",(long)statbuf.st_size);
printf(" %s ",entry->d_name);
printf("
");
}
}
void mode_to_letters(int mode,char str[])
{
strcpy(str,"----------");
if(S_ISDIR(mode)) str[0]='d';
if(S_ISCHR(mode)) str[0]='c';
if(S_ISBLK(mode)) str[0]='b';
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;
if((pw_ptr=getpwuid(uid))!=NULL)
return (pw_ptr->pw_name);
else
return NULL;
}
char *gid_to_name(gid_t gid)
{
struct group *getgrid,*grp_ptr;
if((grp_ptr=getgrgid(gid))!=NULL)
return (grp_ptr->gr_name);
else
return NULL;
}