ls简介
ls是我们使用Linux最常用的命令,可以用来打印当前目录或者制定目录的清单,显示出文件的一些信息等。 ls -a可以将目录下的全部文件(包括隐藏文件)显示出来 ls -l 列出长数据串,包括文件的属性和权限等数据 ls -r将排序结果反向输出,例如:原本文件名由小到大,反向则由大到小 ls -R连同子目录一同显示出来,也就所说该目录下所有文件都会显示出来(显示隐藏文件要加-a参数) 简单的介绍就到这了,我们放码说话。
代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
#include<sys/stat.h>
#include<unistd.h>
#include<sys/types.h>
#include<limits.h>
#include<dirent.h>
#include<grp.h>
#include<pwd.h>
#include<errno.h>
#include<stdlib.h>
#define PARAM_NONE 0
#define PARAM_A 1
#define PARAM_L 2
#define PARAM_R 4
#define PARAM_r 8
#define MAXROWLEN 80
char PATH[PATH_MAX+
1];
int flag;
int g_leave_len = MAXROWLEN;
int g_maxlen;
void my_err(
const char* err_string,
int line);
void display_dir(
char* path);
void my_err(
const char* err_string,
int line)
{
fprintf(stderr,
"line:%d",__LINE__);
perror(err_string);
exit(
1);
}
void cprint(
char* name,mode_t st_mode)
{
if(S_ISLNK(st_mode))
printf(
"\033[1;36m%-*s\033[0m",g_maxlen,name);
else if(S_ISDIR(st_mode)&&(st_mode&
000777)==
0777)
printf(
"\033[1;34;42m%-*s \033[0m",g_maxlen,name);
else if(S_ISDIR(st_mode))
printf(
"\033[1;34m%-*s \033[0m",g_maxlen,name);
else if(st_mode&S_IXUSR||st_mode&S_IXGRP||st_mode&S_IXOTH)
printf(
"\033[1;32m%-*s \033[0m",g_maxlen,name);
else
printf(
"%*s ",g_maxlen,name);
}
void display_attribute(
char* name)
{
struct stat buf;
char buff_time[
32];
struct passwd* psd;
struct group* grp;
if(lstat(name,&buf)==-
1)
{
my_err(
"stat",__LINE__);
}
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))
printf(
"f");
else if(S_ISSOCK(buf.st_mode))
printf(
"s");
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(
" ");
psd=getpwuid(buf.st_uid);
grp=getgrgid(buf.st_gid);
printf(
"M ",buf.st_nlink);
printf(
"%-8s ",psd->pw_name);
printf(
"%-8s ",grp->gr_name);
printf(
"m",buf.st_size);
strcpy(buff_time,ctime(&buf.st_mtime));
buff_time[
strlen(buff_time)-
1]=
'\0';
printf(
" %s ",buff_time);
cprint(name,buf.st_mode);
printf(
"\n");
}
void displayR_attribute(
char* name)
{
struct stat buf;
if(lstat(name,&buf)==-
1)
{
my_err(
"stat",__LINE__);
}
if(S_ISDIR(buf.st_mode))
{
display_dir(name);
free(name);
char* p=PATH;
while(*++p);
while(*--p!=
'/');
*p=
'\0';
chdir(
"..");
return;
}
}
void display_single(
char* name)
{
int len ;
struct stat buf;
if(lstat(name,&buf)==-
1)
{
return;
}
if(g_leave_len<g_maxlen)
{
printf(
"\n");
g_leave_len=MAXROWLEN;
}
cprint(name,buf.st_mode);
g_leave_len=g_leave_len-(g_maxlen+
2);
}
void displayR_single(
char* name)
{
int len ;
struct stat buf;
if(lstat(name,&buf)==-
1)
{
return;
}
if(S_ISDIR(buf.st_mode))
{
printf(
"\n");
g_leave_len=MAXROWLEN;
display_dir(name);
free(name);
char*p=PATH;
while(*++p);
while(*--p!=
'/');
*p=
'\0';
chdir(
"..");
}
}
void display(
char **name ,
int count)
{
switch(flag)
{
int i;
case PARAM_r:
case PARAM_NONE:
for(i=
0;i<count;i++)
{
if(name[i][
0]!=
'.')
display_single(name[i]);
}
break;
case PARAM_r+PARAM_A:
case PARAM_A:
for(i=
0;i<count;i++)
{
display_single(name[i]);
}
break;
case PARAM_r+PARAM_L:
case PARAM_L:
for(i=
0;i<count;i++)
{
if(name[i][
0]!=
'.')
{
display_attribute(name[i]);
}
}
break;
case PARAM_R+PARAM_r:
case PARAM_R:
for(i=
0;i<count;i++)
{
if(name[i][
0]!=
'.')
{
display_single(name[i]);
}
}
for(i=
0;i<count;i++)
{
if(name[i][
0]!=
'.')
{
displayR_single(name[i]);
}
}
break;
case PARAM_L+PARAM_r+PARAM_R:
case PARAM_R+PARAM_L:
for(i=
0;i<count;i++)
{
if(name[i][
0]!=
'.')
{
display_attribute(name[i]);
}
}
for(i=
0;i<count;i++)
{
if(name[i][
0]!=
'.')
{
displayR_attribute(name[i]);
}
}
break;
case PARAM_A+PARAM_r+PARAM_R:
case PARAM_R+PARAM_A:
for(i=
0;i<count;i++)
{
display_single(name[i]);
}
for(i=
0;i<count;i++)
{
if(name[i][
0]!=
'.')
{
displayR_single(name[i]);
}
}
break;
case PARAM_A+PARAM_L+PARAM_r:
case PARAM_A+PARAM_L:
for(i=
0;i<count;i++)
{
display_attribute(name[i]);
}
break;
case PARAM_A+PARAM_L+PARAM_R+PARAM_r:
case PARAM_A+PARAM_L+PARAM_R:
for(i=
0;i<count;i++)
{
display_attribute(name[i]);
}
for(i=
0;i<count;i++)
{
if(name[i][
0]!=
'.')
{
displayR_attribute(name[i]);
}
}
break;
default:
break;
}
}
void display_dir(
char* path)
{
DIR* dir;
struct dirent* ptr;
int count=
0;
if((flag&PARAM_R)!=
0)
{
int len =
strlen(PATH);
if(len>
0)
{
if(PATH[len-
1]==
'/')
PATH[len-
1]=
'\0';
}
if(path[
0]==
'.'||path[
0]==
'/')
{
strcat(PATH,path);
}
else
{
strcat(PATH,
"/");
strcat(PATH,path);
}
printf(
"%s:\n",PATH);
}
dir = opendir(path);
if(dir==NULL)
my_err(
"opendir",__LINE__);
g_maxlen=
0;
while((ptr=readdir(dir))!=NULL)
{
if(g_maxlen<
strlen(ptr->d_name))
g_maxlen=
strlen(ptr->d_name);
count++;
}
closedir(dir);
char **filenames=(
char**)
malloc(
sizeof(
char*)*count),temp[PATH_MAX+
1];
for(
int i=
0;i<count;i++)
{
filenames[i]=(
char*)
malloc(
sizeof(
char)*PATH_MAX+
1);
}
int i,j;
dir=opendir(path);
for(i=
0;i<count;i++)
{
ptr=readdir(dir);
if(ptr==NULL)
{
my_err(
"readdir",__LINE__);
}
strcpy(filenames[i],ptr->d_name);
}
closedir(dir);
if(flag&PARAM_r)
{
for(i=
0;i<count-
1;i++)
{
for(j=
0;j<count-
1-i;j++)
{
if(
strcmp(filenames[j],filenames[j+
1])<
0)
{
strcpy(temp,filenames[j]);
strcpy(filenames[j],filenames[j+
1]);
strcpy(filenames[j+
1],temp);
}
}
}
}
else
{
for(i=
0;i<count-
1;i++)
{
for(j=
0;j<count-
1-i;j++)
{
if(
strcmp(filenames[j],filenames[j+
1])>
0)
{
strcpy(temp,filenames[j]);
strcpy(filenames[j],filenames[j+
1]);
strcpy(filenames[j+
1],temp);
}
}
}
}
if(chdir(path)<
0)
{
my_err(
"chdir",__LINE__);
}
display(filenames,count);
if((flag&PARAM_L==
0&&!(flag|PARAM_R)))
printf(
"\n");
}
int main(
int argc,
char** argv)
{
int i,j,k=
0,num=
0;
char param[
32]=
"";
char *path[
1];
path[
0]=(
char*)
malloc(
sizeof(
char)*(PATH_MAX+
1));
flag=PARAM_NONE;
struct stat buf;
for(i=
1;i<argc;i++)
{
if(argv[i][
0]==
'-')
{
for(j=
1;j<
strlen(argv[i]);j++)
{
param[k]=argv[i][j];
k++;
}
num++;
}
}
param[k]=
'\0';
for(i=
0;i<k;i++)
{
if(param[i]==
'a')
flag|=PARAM_A;
else if(param[i]==
'l')
flag|=PARAM_L;
else if(param[i]==
'R')
flag|=PARAM_R;
else if(param[i]==
'r')
flag|=PARAM_r;
else
{
printf(
"my_ls:invalid option -%c\n",param[i]);
exit(
0);
}
}
if(num+
1==argc)
{
strcpy(path[
0],
".");
display_dir(path[
0]);
return 0;
}
i=
1;
do
{
if(argv[i][
0]==
'-')
{
i++;
continue;
}
else
{
strcpy(path[
0],argv[i]);
if(stat(argv[i],&buf)==-
1)
{
my_err(
"stat",__LINE__);
}
if(S_ISDIR(buf.st_mode))
{
display_dir(path[
0]);
i++;
}
else
{
display(path,
1);
i++;
}
}
}
while(i<argc);
printf(
"\n");
return 0;
}
注意
在我们用ls -R / 这条命令时,我们首先应当切换到root用户,因为一些目录只有root用户才能打开,而在我们的程序中如果打开目录失败则会报错,并终止程序。 以及在访问“/proc”的时候会出现找不到文件的情况,我们应当忽略这种错误,让程序继续进行下去,因为/proc是虚拟文件系统,在系统运行过程中proc中的文件在不断的变化,因此找不到文件属于正常现象,如果我们使用perror报错的话,程序在报错后会自动结束,因此我们应当将perror更改为其他方式的报错,或者,直接去掉这方面的报错。 由于我使用的是fedora的系统在用自己的程序在root权限下递归访问根目录的时候没有出现权限不足的情况,因此就没有更改报错的函数。 如果大家遇到连root权限都不足的情况(因为有的目录是root用户都无法打开的),比如我的一些小伙伴在用系统自带的ls ,执行”sudo ls -alR /run/user/1000”时会提示权限不足,,此时我们可以在lstat的错误处理函数中再加一个判断选项,判断errno是否等于13,如果等于13代表没有访问该目录的权限。此时我们可以或略这个目录,直接return,去访问其他目录即可。(这里要谢谢提供帮助的学长!)