linux c模拟ls命令详解

本篇文章是对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);
}

时间: 2024-08-29 08:18:34

linux c模拟ls命令详解的相关文章

linux c模拟ls命令详解_C 语言

复制代码 代码如下: /* 模拟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>#includ

linux 下的yum命令详解_Linux

yum(全称为 Yellow dog Updater, Modified)是一个在Fedora和RedHat以及SUSE中的Shell前端软件包管理器.基於RPM包管理,能够从指定的服务器自动下载RPM包并且安装,可以自动处理依赖性关系,并且一次安装所有依赖的软体包,无须繁琐地一次次下载.安装.yum提供了查找.安装.删除某一个.一组甚至全部软件包的命令,而且命令简洁而又好记. yum的命令形式一般是如下:yum [options] [command] [package ...] 其中的[opt

Linux下的chkconfig命令详解_Linux

chkconfig命令 Linux下的chkconfig命令主要用来更新(启动或停止)和查询系统服务的运行级信息.谨记chkconfig不是立即自动禁止或激活一个服务,它只是简单的改变了符号连接. 使用语法 chkconfig [–add][–del][–list][系统服务] 或 chkconfig [–level <等级代号>][系统服务][on/off/reset] chkconfig在没有参数运行时,显示用法.如果加上服务名,那么就检查这个服务是否在当前运行级启动.如果是,返回true

Linux系统命令中screen命令详解_Linux

前言 对于执行长时间命令(如大文件运输)而言,为了不让它终止,都会开启一个远程登陆会话窗口来单独运行这样的命令.在此期间,不能关闭远程登录会话窗口或者断开连接,否则前功尽弃.这时候screen命令就派上用场了. Screen是一款由GNU计划开发的用于命令行终端切换的自由软件.用户可以通过该软件同时连接多个本地或远程的命令行会话,并在其间自由切换.GNU Screen可以看作是窗口管理器的命令行界面版本.它提供了统一的管理多个会话的界面和相应的功能. 下面来介绍下我最常用的screen命令(仅限

Linux中的curl命令详解_Linux

语法 # curl [option] [url] 常见参数: -A/--user-agent <string> 设置用户代理发送给服务器 -b/--cookie <name=string/file> cookie字符串或文件读取位置 -c/--cookie-jar <file> 操作结束后把cookie写入到这个文件中 -C/--continue-at <offset> 断点续转 -D/--dump-header <file> 把header信息

Linux 中 CURL常用命令详解_linux shell

下载单个文件,默认将输出打印到标准输出中(STDOUT)中 curl http://www.centos.org 通过-o/-O选项保存下载的文件到指定的文件中: -o:将文件保存为命令行中指定的文件名的文件中 -O:使用URL中默认的文件名保存文件到本地 # 将文件下载到本地并命名为mygettext.html curl -o mygettext.html http://www.gnu.org/software/gettext/manual/gettext.html # 将文件保存到本地并命名

Linux ls命令详解 Linux ls命令怎么用

Linux ls命令用于显示指定工作目录下之内容(列出目前工作目录所含之文件及子目录). 语法 ls [-alrtAFR] [name...] 参数: -a 显示所有文件及目录 (ls内定将文件名或目录名称开头为"."的视为隐藏档,不会列出) -l 除文件名称外,亦将文件型态.权限.拥有者.文件大小等资讯详细列出 -r 将文件以相反次序显示(原定依英文字母次序) -t 将文件依建立时间之先后次序列出 -A 同 -a ,但不列出 "." (目前目录) 及 "

linux的网络配置命令详解

1.查看IP:Ifconfig 2.配置IP的方法: A.这种方法立即生效,但是重启将不会保存.(除了这个方法的其它方法都可以保存下来) Ifconfig eth0 1.1.1.1 netmask 255.0.0.0 up Ifconfig eth0:1 1.1.1.3 up //设置一个网卡多个IP的方法(在设置虚拟主机时有用到) 激活网卡:Ifconfig eth0 up 关闭网卡:Ifconfig eth0 down 动态获取IP:Ifconfig etho –dynamic Dhclie

Linux关机和重启命令详解

  Linux有如下的关机和重启命令:shutdown, reboot, halt, poweroff,那么它们有什么区别呢? shutdown - 建议使用的命令 shutdown是最常用也是最安全的关机和重启命令,它会在关机之前调用fsck检查磁盘,其中-h和-r是最常用的参数:-h:停止系统服务并关机 -r: 停止系统服务后重启 下面看几个例子:shutdown -h now --立即关机 shutdown -h 10:53 --到10:53关机,如果该时间小于当前时间,则到隔天 shut