linux c模拟ls命令详解
2014-09-05来源:

本篇文章是对linux中基于c模拟ls命令的实现方法进行了详细的分析介绍,需要的朋友参考下

代码如下:

/*

模拟ls命令,实现参数-tariRl.有些代码重复出现,可改进

可以在该程序的基础上增加参数,该程序思路清晰,容易扩展

*/

#include<stdio.h>

#include<string.h>

#include<stdlib.h>

#include<sys/types.h>

#include<unistd.h>

#include<sys/stat.h>

#include<dirent.h>

#include<sys/ioctl.h>

#include<pwd.h>

#include<grp.h>

#define LL (1<<0) /*带l参数标志*/

#define IL (1<<1) /*带i参数标志*/

#define RU (1<<2) /*带R参数标志*/

#define TL (1<<16) /*带t参数标志*/

#define AL (1<<17) /*带a参数标志*/

#define RL (1<<18) /*带r参数标志*/

#define LENGTH 500 /*字符串最大长度*/

#define MAX_FILE_COUNT 500/*文件列表最大长度*/

/*函数声明*/

void error(char* error_message,int line);

void display(struct stat* stalist,char (*namelist)[LENGTH],int n,int mode);

int file_list(char* path,struct stat* stalist,char (*namelist)[LENGTH],int mode);

void display_simply(char (*namelist)[LENGTH],int n);

void display_LL(struct stat * stalist,char (*namelist)[LENGTH],int n);

void display_IL(struct stat * stalist,char (*namelist)[LENGTH],int n);

void display_LL_IL(struct stat * stalist,char (*namelist)[LENGTH],int n);

void display_RU(struct stat* stalist,char (*namelist)[LENGTH],int n,int mode);

void display_RU_LL(struct stat * stalist,char (*namelist)[LENGTH],int n,int mode);

void display_RU_IL(struct stat* stalist,char (*namelist)[LENGTH],int n,int mode);

void display_RU_IL_LL(struct stat * stalist,char (*namelist)[LENGTH],int n,int mode);

/*主函数*/

int main(int argc,char **argv)

{

int i,j;

/*mode的前16个位用来标志那些能影响显示的参数,16位之后的位用来标志不影响输出格式的参数。这个程序只用到了0-3位,16-18位,如果要在该程序的基础上增加参数,可以用其他没有使用的位。

mode的第0位为1表示带l参数,mode的第1位为1表示带i参数,mode的第2位为1表示带R参数,mode的第16位为1表示带t参数,mode的第17位为1表示带a参数,mode的第18位为1表示带r参数*/

int mode=0;

char error_message[LENGTH]={0};/*错误信息*/

char path[LENGTH]={0};/*路径*/

struct stat stalist[MAX_FILE_COUNT];/*文件详细信息数组*/

char namelist[MAX_FILE_COUNT][LENGTH];/*文件名数组*/

int flag=0;/*判断是否指定了目录*/

int count;/*文件个数*/

/*解析参数*/

for(i=1;i<argc;i++){

if(argv[i][0]=='-'){/*如果是选项参数*/

for(j=1;j<strlen(argv[i]);j++){

if(argv[i][j]=='l')

mode=mode|LL;

else if(argv[i][j]=='i')

mode=mode|IL;

else if(argv[i][j]=='R')

mode=mode|RU;

else if(argv[i][j]=='r')

mode=mode|RL;

else if(argv[i][j]=='a')

mode=mode|AL;

else if(argv[i][j]=='t')

mode=mode|TL;

else{

snprintf(error_message,LENGTH,"no option of %c",argv[i][j]);

error(error_message,__LINE__);

}

}

}else{/*参数为目录或文件*/

if(flag==1)

error("can not specify more then two dir or file",__LINE__);

else

flag=1;

if(argv[i][0]!='/'){/*相对路径*/

strcat(path,get_current_dir_name());

strcat(path,"/");

strncat(path,argv[i],strlen(argv[i]));

}else/*绝对路径*/

strcpy(path,argv[i]);

}

}

if(flag==0)/*未指定任何目录或文件,则使用默认当前目录*/

strcat(path,get_current_dir_name());

/*根据mode获取指定目录下的文件*/

count=file_list(path,stalist,namelist,mode);

/*根据mode显示文件*/

display(stalist,namelist,count,mode);

return 0;

}

/*获取文件列表*/

int file_list(char* path,struct stat* stalist,char (*namelist)[LENGTH],int mode)

{

int i=0,index,j,k;

DIR *dir;

struct dirent *ptr;

char str[LENGTH];

char nametemp[LENGTH];

struct stat statemp;

if(stat(path,&stalist[0])<0){

// puts(path);

error("the specify file is not exist",__LINE__);

}

if(S_ISDIR(stalist[0].st_mode)){/*如果该路径指向的是一个目录*/

if((dir=opendir(path))==NULL){/*打开目录*/

sprintf(str,"can not open %s",path);

error(str,__LINE__);

}

chdir(path);/*改变当前工作目录到path*/

i=0;

while((ptr=readdir(dir))!=NULL){/*依次读取目录下的所有文件*/

if(ptr->d_name[0]=='.' && !(mode & AL))/*忽略隐藏文件*/

continue;

/*按字母顺序插入到stalist数组及namelist数组*/

for(j=i;j>0;j--){

if(strcmp(ptr->d_name,namelist[j-1])>0)

break;

}

for(k=i;k>j;k--){

strcpy(namelist[k],namelist[k-1]);

stalist[k]=stalist[k-1];

}

strcpy(namelist[j],ptr->d_name);

stat(ptr->d_name,&stalist[j]);

i++;

if(i==MAX_FILE_COUNT)

error("file count beyond MAX_FILE_COUNT",__LINE__);

}

closedir(dir);

}else{

j=strlen(path)-1;

while(j>=0 && path[j]!='/'){

j--;

}

if(j<0)

error("path error",__LINE__);

j++;

k=0;

while(path[j]){

namelist[0][k]=path[j];

j++;

k++;

}

namelist[0][k]=0;

return 1;

}

if(mode & TL){/*按文件修改时间排序*/

for(j=0;j<i;j++){

index=j;

for(k=j+1;k<i;k++)

if(stalist[index].st_mtime<stalist[k].st_mtime){

index=k;

}

statemp=stalist[j];

stalist[j]=stalist[index];

stalist[index]=statemp;

strcpy(nametemp,namelist[j]);

strcpy(namelist[j],namelist[index]);

strcpy(namelist[index],nametemp);

}

}

if(mode & RL){/*反序排列*/

for(j=0;j<i/2;j++){

strcpy(nametemp,namelist[j]);

strcpy(namelist[j],namelist[i-j-1]);

strcpy(namelist[i-j-1],nametemp);

statemp=stalist[j];

stalist[j]=stalist[i-j-1];

stalist[i-j-1]=statemp;

}

}

return i;

}

/*根据mode选择不同的函数进行显示*/

void display(struct stat* stalist,char (*namelist)[LENGTH],int n,int mode)

{

/*使mode的高16位为0*/

int m = mode & ((1<<16)-1);

switch(m){

case 0:

display_simply(namelist,n);

break;

case 1:

display_LL(stalist,namelist,n);

break;

case 2:

display_IL(stalist,namelist,n);

break;

case 3:

display_LL_IL(stalist,namelist,n);

break;

case 4:

display_RU(stalist,namelist,n,mode);

break;

case 5:

display_RU_LL(stalist,namelist,n,mode);

break;

case 6:

display_RU_IL(stalist,namelist,n,mode);

break;

case 7:

display_RU_IL_LL(stalist,namelist,n,mode);

break;

}

}

/*不带显示选项,简单显示文件名*/

void display_simply(char (*namelist)[LENGTH],int n)

{

int i,maxlength=0,cols;

struct winsize ts;

for(i=0;i<n;i++)

if(strlen(namelist[i])>maxlength)

maxlength=strlen(namelist[i]);

/*获取终端的大小*/

ioctl(STDIN_FILENO,TIOCGWINSZ,&ts);

cols=ts.ws_col;

cols/=(maxlength+1);

//lines=ts.ws_row;

for(i=0;i<n;i++){

if(i!=0 && i%cols==0)

puts("");

printf("%*s",-(maxlength+1),namelist[i]);

}

putchar('n');

}

/*-l 参数,显示详细文件信息*/

void display_LL(struct stat * stalist,char (*namelist)[LENGTH],int n)

{

int i,mode;

char* str;

for(i=0;i<n;i++){

mode=stalist[i].st_mode;

if(S_ISDIR(mode))

printf("d");

else

printf("-");

if(mode & (1<<8))

printf("r");

else

printf("-");

if(mode & (1<<7))

printf("w");

else

printf("-");

if(mode & (1<<6))

printf("x");

else

printf("-");

if(mode & (1<<5))

printf("r");

else

printf("-");

if(mode & (1<<4))

printf("w");

else

printf("-");

if(mode & (1<<3))

printf("x");

else

printf("-");

if(mode & (1<<2))

printf("r");

else

printf("-");

if(mode & (1<<1))

printf("w");

else

printf("-");

if(mode & (1<<0))

printf("x");

else

printf("-");

printf(" %-3d",stalist[i].st_nlink);

printf(" %-6s",getpwuid(stalist[i].st_uid)->pw_name);

printf(" %-6s",getgrgid(stalist[i].st_gid)->gr_name);

printf(" %-10d",stalist[i].st_size);

str=ctime(&stalist[i].st_mtime);

str[strlen(str)-2]=0;

printf(" %s",str);

printf(" %sn",namelist[i]);

}

}

/*-i 参数,显示文件名及节点号*/

void display_IL(struct stat* stalist,char (*namelist)[LENGTH],int n)

{

int i,maxlength=0,cols;

struct winsize ts;

for(i=0;i<n;i++)

if(strlen(namelist[i])>maxlength)

maxlength=strlen(namelist[i]);

/*获取终端的大小*/

ioctl(STDIN_FILENO,TIOCGWINSZ,&ts);

cols=ts.ws_col;

cols/=(maxlength+9);

//lines=ts.ws_row;

for(i=0;i<n;i++){

if(i!=0 && i%cols==0)

puts("");

printf("%-8d ",stalist[i].st_ino);

printf("%*s",-(maxlength+1),namelist[i]);

}

putchar('n');

}

/*-li 参数,显示详细文件信息和节点号*/

void display_LL_IL(struct stat * stalist,char (*namelist)[LENGTH],int n)

{

int i,mode;

char* str;

for(i=0;i<n;i++){

printf("%-8d ",stalist[i].st_ino);

mode=stalist[i].st_mode;

if(S_ISDIR(mode))

printf("d");

else

printf("-");

if(mode & (1<<8))

printf("r");

else

printf("-");

if(mode & (1<<7))

printf("w");

else

printf("-");

if(mode & (1<<6))

printf("x");

else

printf("-");

if(mode & (1<<5))

printf("r");

else

printf("-");

if(mode & (1<<4))

printf("w");

else

printf("-");

if(mode & (1<<3))

printf("x");

else

printf("-");

if(mode & (1<<2))

printf("r");

else

printf("-");

if(mode & (1<<1))

printf("w");

else

printf("-");

if(mode & (1<<0))

printf("x");

else

printf("-");

printf(" %-3d",stalist[i].st_nlink);

printf(" %-6s",getpwuid(stalist[i].st_uid)->pw_name);

printf(" %-6s",getgrgid(stalist[i].st_gid)->gr_name);

printf(" %-10d",stalist[i].st_size);

str=ctime(&stalist[i].st_mtime);

str[strlen(str)-2]=0;

printf(" %s",str);

printf(" %sn",namelist[i]);

}

}

/*-R 参数,简单显示所有文件,包括目录下面的子目录*/

void display_RU(struct stat* stalist,char (*namelist)[LENGTH],int n,int mode)

{

int i,count;

char path[LENGTH]={0},temp[LENGTH]={0};

struct stat sta[MAX_FILE_COUNT];

char name[MAX_FILE_COUNT][LENGTH];

puts(get_current_dir_name());

display_simply(namelist,n);

putchar('n');

strcpy(path,get_current_dir_name());

for(i=0;i<n;i++){

if(strcmp(namelist[i],".")==0 || strcmp(namelist[i],"..")==0)

continue;

if(S_ISDIR(stalist[i].st_mode)){

strcpy(temp,path);

strcat(path,"/");

strcat(path,namelist[i]);

count=file_list(path,sta,name,mode);

display_RU(sta,name,count,mode);

strcpy(path,temp);

}

}

}

/*-Rl 参数,显示所有文件,包括目录下面的子目录的详细信息*/

void display_RU_LL(struct stat * stalist,char (*namelist)[LENGTH],int n,int mode)

{

int i,count;

char path[LENGTH]={0},temp[LENGTH]={0};

struct stat sta[MAX_FILE_COUNT];

char name[MAX_FILE_COUNT][LENGTH];

puts(get_current_dir_name());

display_LL(stalist,namelist,n);

putchar('n');

strcpy(path,get_current_dir_name());

for(i=0;i<n;i++){

if(strcmp(namelist[i],".")==0 || strcmp(namelist[i],"..")==0)

continue;

if(S_ISDIR(stalist[i].st_mode)){

strcpy(temp,path);

strcat(path,"/");

strcat(path,namelist[i]);

count=file_list(path,sta,name,mode);

display_RU_LL(sta,name,count,mode);

strcpy(path,temp);

}

}

}

/*-Ri 参数,简单显示所有文件,包括目录下的子目录,及节点号*/

void display_RU_IL(struct stat* stalist,char (*namelist)[LENGTH],int n,int mode)

{

int i,count;

char path[LENGTH]={0},temp[LENGTH]={0};

struct stat sta[MAX_FILE_COUNT];

char name[MAX_FILE_COUNT][LENGTH];

puts(get_current_dir_name());

display_IL(stalist,namelist,n);

putchar('n');

strcpy(path,get_current_dir_name());

for(i=0;i<n;i++){

if(strcmp(namelist[i],".")==0 || strcmp(namelist[i],"..")==0)

continue;

if(S_ISDIR(stalist[i].st_mode)){

strcpy(temp,path);

strcat(path,"/");

strcat(path,namelist[i]);

count=file_list(path,sta,name,mode);

display_RU_IL(sta,name,count,mode);

strcpy(path,temp);

}

}

}

/*-Ril 参数,显示所有文件,包括目录下面的子目录的详细信息,及节点号*/

void display_RU_IL_LL(struct stat * stalist,char (*namelist)[LENGTH],int n,int mode)

{

int i,count;

char path[LENGTH]={0},temp[LENGTH]={0};

struct stat sta[MAX_FILE_COUNT];

char name[MAX_FILE_COUNT][LENGTH];

puts(get_current_dir_name());

display_LL_IL(stalist,namelist,n);

putchar('n');

strcpy(path,get_current_dir_name());

for(i=0;i<n;i++){

if(strcmp(namelist[i],".")==0 || strcmp(namelist[i],"..")==0)

continue;

if(S_ISDIR(stalist[i].st_mode)){

strcpy(temp,path);

strcat(path,"/");

strcat(path,namelist[i]);

count=file_list(path,sta,name,mode);

display_RU_IL_LL(sta,name,count,mode);

strcpy(path,temp);

}

}

}

//错误处理函数

void error(char* error_message,int line)

{

char str[5];

sprintf(str,"%d:",line);

strcat(str,error_message);

perror(str);

exit(EXIT_FAILURE);

}

更多信息请查看IT技术专栏

2025公考·省考培训课程试听预约报名

  • 报班类型
  • 姓名
  • 手机号
  • 验证码
推荐信息
Baidu
map