Linux使用C语言实现ls命令

原理

在linux下使用C语言,通过调用Linux系统的目录访问API来实现一个类似于ls命令功能的小程序,主要是可以练习程序对命令的解析和目录API函数的使用。

实现代码

#include <stdio.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <pwd.h>
#include <grp.h>

int aflag = 0,lflag = 0;

void display_file(char *fname , char *nname)
{
	struct stat buf;
	struct tm *t;
	int i;

	if(stat(fname,&buf) < 0)
	{
		perror("stat error\n");
		return ;
	}

	switch(buf.st_mode & S_IFMT)
	{
	case S_IFSOCK:	printf("s");	break;
	case S_IFLNK:	printf("l");	break;
	case S_IFREG:	printf("-");	break;
	case S_IFBLK:	printf("b");	break;
	case S_IFDIR:	printf("d");	break;
	case S_IFCHR:	printf("c");	break;
	case S_IFIFO:	printf("p");	break;
	}

	for(i = 8 ; i >= 0 ; i--)
	{
		if(buf.st_mode & (1 << i))
		{
			if(i % 3 == 2)	printf("r");
			if(i % 3 == 1)	printf("w");
			if(i % 3 == 0)	printf("x");
		}
		else
			printf("-");
	}


	printf(" %d ",buf.st_nlink);

	printf("%s ",getpwuid(buf.st_uid)->pw_name);
	printf("%s ",getgrgid(buf.st_gid)->gr_name);

	printf("%ld ",buf.st_size);

	t = localtime(&buf.st_mtime);
	printf("%d-%02d-%02d  %02d:%02d ",t->tm_year+1900,t->tm_mon+1,t->tm_mday,
			t->tm_hour,t->tm_min);
	printf("%s\n",nname);

	return ;
}

void display_dir(char *dir)
{
	DIR *mydir;
	struct dirent *myitem;
	char fname[256];

	if((mydir = opendir(dir)) == NULL)
	{
		perror("fail to opendir!\n");
		return ;
	}
	while((myitem = readdir(mydir)) != NULL)
	{
		if(myitem->d_name[0] == '.' && 
		 !aflag)//如果if条件成立的就继续下一次循环,否则往下执行
			continue;

		if(lflag)//ls -l -a dir
		{

			sprintf(fname,"%s/%s",dir,myitem->d_name);
			display_file(fname,myitem->d_name);
		}
		else // ls dir
			printf("%s  ",myitem->d_name);
	}
	printf("\n");
	closedir(mydir);
	return ;
}

int main(int argc,char *argv[])
{
	int ch,i;
	struct stat buf;

	opterr = 0;
	//解析命令
	while((ch = getopt(argc,argv,"la")) != -1)
	{
		switch(ch)
		{
		case 'a':	aflag = 1;	break;
		case 'l':	lflag = 1;	break;
		default:	printf("wrong option:%c\n",optopt);return -1;
		}
	}

	if(optind == argc)//no argument //ls .没有带参直接ls当前目录
		display_dir(".");

	for(i = optind; i < argc ; i++) //ls name1 name2....
	{
		if(stat(argv[i],&buf) < 0)
		{
			perror("fail to stat!\n");
			return -1;
		}
		if(S_ISDIR(buf.st_mode))//dir
		{
			printf("%s:\n",argv[i]);
			display_dir(argv[i]);
		}
		else//file
			if(lflag)//ls -l file
				display_file(argv[i],argv[i]);
			else// ls file
				printf("%s",argv[i]);
		printf("\n");
	}

	return 0;
}

编译

gcc test.c -o test

运行

直接运行,输出当前目录的文件:

./test 
test  test.c   

跟个参数,输出详细信息:

./test -l
-rwxrwxr-x 1 root root 13637 2020-04-15  07:37 test
-rw-r--r-- 1 root root 2409 2014-03-25  06:01 test.c

输出隐藏文件:

./test -a
test  .test.c.bak  test.c  ..  .

欢迎关注微信公众号:
微信公众号

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页