linux下shell解释器 c实现

要求

(1)要求实现的基本命令包括:

  • pwd //显示当前所在目录的路径名
  • list <目录名> //列出指定目录名中的所有目录及文件
  • chadir <目录名或路径> //改变当前工作目录
  • makedir <目录名> //新建目录
  • deldir <目录名> //删除目录
  • exit //退出命令解释程序

(2)可选做的扩展命令包括:

  • rename <旧文件名> <新文件名> //重命名一个文件或目录
  • copy <已存在的文件名> <副本文件名或路径> //复制一个已存在的文件
  • find <目录> -name <待查找的文件名> //在指定的目录及其子目录中查找指定的文件,
    并输出查找到的文件的绝对路径。
  1. 设计要求
    (1) 设计必须在Linux环境下进行。
    (2) 命令解释程序的提示符为:姓名拼音@
    (3) 程序编写中不得使用system()系统调用。
    (4) 整个程序必须严格经过测试,完成所有基本功能。源程序应有较详尽的注释。

完成情况

 pwd
 list
 chadir
 makedir
 deldir
 rename
 copy
 find
 help
 exit
各项基本功能与扩展功能均已完成,
附加帮助功能
附加颜色打印
动态检查命令,实现类似于开发平台检查指令并变换颜色功能
增强错误检查,一定程度上提高了容错率

效果截图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码

  1. 程序头文件
    <stdio.h> C 标准库 主要用于一些标准输入输出
    <stdlib.h> standard library标准库头文件
    <termios.h> Linux 下串口驱动头文件
    <unistd.h> 提供对 POSIX 操作系统 API 的访问功能的头文件
    <string.h> 字符串处理
    <dirent.h> 主要用于文件系统的目录读取操作
    <fcntl.h> 文件控制选项头文件
    <sys/types.h> 基本系统数据类型的头文件,含有size_t,time_t,pid_t等类型
    <sys/stat.h> 用到stat 结构体
    <time.h> 包含获得和使用日期和时间信息的函数的定义

  2. 宏定义
    #define CLOSE printf("\033[0m"); 关闭彩色字体
    #define RED printf("\033[31m"); 红色字体 警告或错误
    #define GREEN printf("\033[36m"); 深绿色字体 指令
    #define GREEN2 printf("\033[32m"); 绿色字体 命令解释程序的提示符
    #define YELLOW printf("\033[33m"); 黄色字体 文件
    #define BLUE printf("\033[34m"); 蓝色字体 文件夹
    #define LIGHT printf("\033[1m"); 高亮
    #define MOVERIGHT(y) printf("\033[%dC",(y)) 右移光标
    #define RESET_CURSOR() printf("\033[u") 恢复光标

  3. 函数声明
    void GetOrder(char*order); 获取命令函数,包括设置颜色
    void PrintOrder(char*order); 设置打印颜色
    int IsOrder(char*order); 检查命令
    void Pwd(); 显示当前所在目录的路径名
    void List(); 列出指定目录名中的所有目录及文件
    void Chadir(); 改变当前工作目录
    void Makedir(); 新建目录
    void Deldir(); 删除目录
    void Exit(); 退出命令解释程序
    void Rename(); 重命名一个文件或目录
    void Copy(); 复制一个已存在的文件
    void Find(); 在指定的目录及其子目录中查找指定的文件,并输出查找到的文件的绝对路径。
    **void Find2(char *path, char name, int flag); Find的递归调用
    void Helps(); 提示相关功能
    void PrintfAll(); 打印所有指令

//相关头文件
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <unistd.h>
#include <string.h>
//
#include<dirent.h>	//opendir()  readdir()	closedir()	  dirent、DIR...
#include<fcntl.h>//
#include<sys/types.h>
#include<sys/stat.h>
#include <time.h>
//宏定义颜色输出
#define CLOSE printf("\033[0m"); //关闭彩色字体
#define RED printf("\033[31m"); //红色字体 警告或错误
#define GREEN printf("\033[36m");//深绿色字体 指令
#define GREEN2 printf("\033[32m");//绿色字体 命令解释程序的提示符
#define YELLOW printf("\033[33m");//黄色字体 文件
#define BLUE printf("\033[34m");//蓝色字体   文件夹
#define LIGHT printf("\033[1m");//高亮
//宏定义光标移动
#define MOVERIGHT(y) printf("\033[%dC",(y))// 右移光标
#define RESET_CURSOR() printf("\033[u")// 恢复光标
//函数申明
void GetOrder(char*order); //获取命令函数,包括设置颜色
void PrintOrder(char*order); //设置打印颜色
int IsOrder(char*order); //检查命令
void Pwd(); //显示当前所在目录的路径名
void List(); //<目录名> 列出指定目录名中的所有目录及文件
void Chadir(); //<目录名或路径> 改变当前工作目录
void Makedir(); //<目录名> 新建目录
void Deldir(); //<目录名> 删除目录
void Exit(); //退出命令解释程序
//扩展命令:
void Rename(); //<旧文件名> <新文件名> 重命名一个文件或目录
void Copy(); //<已存在的文件名> <副本文件名或路径> 复制一个已存在的文件
void Find(); //<目录> -name <待查找的文件名> 在指定的目录及其子目录中查找指定的文件,并输出查找到的文件的绝对路径。
void Find2(char *path, char *name, int *flag); //递归调用
void Helps(); //<命令> 提示相关功能
void PrintfAll(); //
//程序入口
int main() {
	char order[100];
	PrintfAll();
	while (1) {
		fflush(stdin);
		strcpy(order, "\0"); //初始化
		GetOrder(order);
		if (!IsOrder(order) && strcmp(order, "\0")) {
			RED
			printf("\n找不到该命令! 输入\"help\" 可查看帮助\n");
			CLOSE
			continue;
		}
		if (!strcmp(order, "exit")) {
			printf("\n");
			break;
		}
		if (!strcmp(order, "pwd")) {
			Pwd();
		}
		if (!strcmp(order, "help")) {
			Helps();
		}
		if (!strcmp(order, "list")) {
			List();
		}
		if (!strcmp(order, "chadir")) {
			Chadir();
		}
		if (!strcmp(order, "makedir")) {
			Makedir();
		}
		if (!strcmp(order, "deldir")) {
			Deldir();
		}
		if (!strcmp(order, "rename")) {
			Rename();
		}
		if (!strcmp(order, "copy")) {
			Copy();
		}
		if (!strcmp(order, "find")) {
			Find();
		}
	}
	return 0;

}

//函数定义
void GetOrder(char*order) {

	int i = 0;
	int i2;
	char ch;
	struct termios oldt, newt;
	LIGHT
	GREEN2
	printf("\nhuangzepen@ ");
	CLOSE
	while (1) {
		tcgetattr(STDIN_FILENO, &oldt);
		newt = oldt;
		newt.c_lflag &= ~(ECHO | ICANON);
		tcsetattr(STDIN_FILENO, TCSANOW, &newt); //输入前关闭终端回显

		ch = getchar();

		if (ch == '\n' || ch == ' ') { //空格或回车
			order[i] = '\0';
			for (i2 = 0; i2 < strlen(order); i2++)
				printf("\b \b"); //让光标左移i位(删除i个字符)
			PrintOrder(order);
			printf(" ");
			tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
			break;
		} else {
			order[i] = ch;
			MOVERIGHT(1);
			i++;
			order[i] = '\0';
			for (i2 = 0; i2 < strlen(order); i2++)
				printf("\b \b"); //让光标左移i位(删除i个字符)
			PrintOrder(order);
		}
		tcsetattr(STDIN_FILENO, TCSANOW, &oldt); //每次输入一个字符后恢复回显状态
	}
	return;
}
void PrintOrder(char*order) {

	if (IsOrder(order)) {
		if (!strcmp(order, "exit")) {
			RED
			printf("%s", order);
			CLOSE
		} else {
			GREEN
			printf("%s", order);
			CLOSE
		} //打印颜色命令
	} else
		printf("%s", order);
}
int IsOrder(char*order) {
	if (!strcmp(order, "pwd") || !strcmp(order, "list")
			|| !strcmp(order, "chadir") || !strcmp(order, "makedir")
			|| !strcmp(order, "deldir") || !strcmp(order, "exit")
			|| !strcmp(order, "pwd") || !strcmp(order, "rename")
			|| !strcmp(order, "copy") || !strcmp(order, "find")
			|| !strcmp(order, "help"))
		return 1;
	else
		return 0;
}
void Pwd() {
	int LENTH = 255;
	char pwds[LENTH];
	if (!getcwd(pwds, LENTH)) {
		RED
		printf("getcwd error\n");
		CLOSE
		return;
	}
	printf("\n当前所在目录的路径为:");
	BLUE
	LIGHT
	printf("%s\n", pwds);
	CLOSE
	return;
}
void Help() {
	char order[100];
	scanf("%s", order);
	printf("%s", order);
}
void List() {
	DIR *dp; //声明一个类似于文件类型的指针
	struct dirent *dirp;
	char dirname[100];
	printf("文件路径:");
	fflush(stdin);
	scanf("%s", dirname);
	getchar();
	if ((dp = opendir(dirname)) == NULL) {
		printf("can’t open %s", dirname);
		return;
	}

	while ((dirp = readdir(dp)) != NULL) {
		if (strcmp(dirp->d_name, ".") == 0 || strcmp(dirp->d_name, "..") == 0) //当前目录或父级目录
			continue;
		else if (dirp->d_type == 8) { //文件
			YELLOW
			LIGHT
			printf("%s\n", dirp->d_name);
			CLOSE
		} else if (dirp->d_type == 10) { //链接文件
			YELLOW
			printf("%s\n", dirp->d_name);
			CLOSE
		} else if (dirp->d_type == 4) { // 目录
			BLUE
			LIGHT
			printf("%s\n", dirp->d_name);
			CLOSE
		}
	}
	closedir(dp);
	return;
}
void Chadir() {
	DIR *dp;
	int LENTH = 255;
	char pwds[LENTH];
	char dirname[100];
	printf("目标工作路径:");
	fflush(stdin);
	scanf("%s", dirname);
	getchar();
	chdir(dirname);
	if ((dp = opendir(dirname)) == NULL) { //检查路径
		RED
		printf("找不到路径 %s", dirname);
		CLOSE
		return;
	} else
		closedir(dp);
	if (!getcwd(pwds, LENTH)) {
		RED
		printf("getcwd error\n");
		CLOSE
		return;
	}
	LIGHT
	GREEN2
	printf("\nhuangzepen@ ");
	CLOSE
	BLUE
	LIGHT
	printf("%s", pwds);
	CLOSE
	return;
}
void Makedir() {
	char path[256]; //目标文件夹路径
	char *path_buf; //目标文件夹路径指针
	char temp_path[256]; // 存放临时文件夹路径
	char *temp; //单级文件夹名称
	int temp_len; //单级文件夹名称长度
	char aim_path[256]; //用户输入
	printf("目录路径:");
	fflush(stdin);
	scanf("%s", aim_path);
	getchar();
	if (!access(aim_path, F_OK)) { // 判断目标文件夹是否存在
		LIGHT
		RED
		printf("目录已存在\n");
		CLOSE
		return;
	}
	memset(path, 0, sizeof(path)); //初始字符内存
	memset(temp_path, 0, sizeof(temp_path));
	strcat(path, aim_path);
	path_buf = path;
	while ((temp = strsep(&path_buf, "/")) != NULL) { //拆分路径
		temp_len = strlen(temp);
		if (0 == temp_len) {
			continue;
		}
		if (!strcmp(".", temp) || !strcmp("..", temp)) {
			strcat(temp_path, temp);
			strcat(temp_path, "/");
		} else {
			strcat(temp_path, "/");
			strcat(temp_path, temp);
		}
		//printf("temp_path =%s\n", temp_path);
		if (-1 == access(temp_path, F_OK)) { /* 不存在则创建 */
			if (-1 == mkdir(temp_path, 0777)) { //最高读写权限
				LIGHT
				RED
				printf("目录创建失败\n");
				CLOSE
				return;
			}
		}
	}
	printf("创建成功\n");
	return;
}
void Deldir() {
	char dirname[100];
	printf("目录路径:");
	fflush(stdin);
	scanf("%s", dirname);
	getchar();
	if (access(dirname, F_OK) == -1) { // 判断目标文件夹是否存在
		LIGHT
		RED
		printf("目录不存在\n");
		CLOSE
		return;
	}
	if (remove(dirname) == 0) {
		printf("%s 已经删除\n", dirname);
	} else {
		LIGHT
		RED
		printf("删除失败,请检查权限\n");
		CLOSE
		return;
	}

}
void Rename() {
	char oldname[100], newname[100];
	printf("旧目录或文件路径: ");
	fflush(stdin);
	scanf("%s", oldname);
	getchar();
	printf(" 您想修改为: ");
	fflush(stdin);
	scanf("%s", newname);
	getchar();
	if (rename(oldname, newname) == 0)
		printf("已经把文件 %s 修改为 %s.\n", oldname, newname);
	else {
		LIGHT
		RED
		printf("rename失败,请检查路径或权限!\n");
		CLOSE
		return;
	}
	return;
}
void Copy() {
	char pathName[100];
	char pathName2[100];
	int in, out, flag;
	char buffer[1024];
	struct stat statbuf;
	printf("请输复制目标文件路径:");
	fflush(stdin);
	scanf("%s", pathName);
	getchar();
	if (access(pathName, F_OK) == -1) { // 判断目标文件夹是否存在
		LIGHT
		RED
		printf("目录不存在\n");
		CLOSE
		return;
	}
	if (stat(pathName, &statbuf) == -1) {
		LIGHT
		RED
		printf("获取文件描述失败\n");
		CLOSE
		return;
	}
	if (S_ISDIR(statbuf.st_mode)) { //目录
		LIGHT
		RED
		printf("该路径为目录\n");
		CLOSE
		return;
	}
	if (S_ISREG(statbuf.st_mode)) { //文件
		printf("文件大小:%ld bytes\t最后修改时间 %s", statbuf.st_size,
				ctime(&statbuf.st_mtime));
	}
	in = open(pathName, O_RDONLY, S_IRUSR);
	if (-1 == in) {
		printf(" 打开文件%s失败!请检查路径或权限!\n", pathName);
		return;
	}
	printf("请输入复制完的文件路径:");
	fflush(stdin);
	scanf("%s", pathName2);
	getchar();
	if (strcmp(pathName2, pathName) == 0) {
		printf("路径相同,将为您生成副本\n");
		strcat(pathName2, "(1)");
	}
	out = creat(pathName2, S_IWUSR);
	if (-1 == in) {
		LIGHT
		RED
		printf("创建文件%s失败!请检查路径或权限!\n", pathName2);
		CLOSE
		return;
	}
	while ((flag = read(in, buffer, 1024)) > 0) {
		write(out, buffer, flag);
	}
	close(in);
	close(out);
	printf("复制文件到%s 完毕!\n", pathName2);
	return;
}
void Find() {
	int flag = 0;
	char path[1000];
	char name[100];
	printf("\n请输入查找一级路径:");
	fflush(stdin);
	scanf("%s", path);
	getchar();
	if (access(path, F_OK) == -1) { // 判断目标文件夹是否存在
		LIGHT
		RED
		printf("路径错误\n");
		CLOSE
		return;
	}
	printf("请输入文件名:");
	fflush(stdin);
	scanf("%s", name);
	getchar();
	Find2(path, name, &flag);
	if (!flag) {
		printf("在路径");
		BLUE
		LIGHT
		printf("%s", path);
		CLOSE
		printf("找不到文件");
		YELLOW
		LIGHT
		printf("%s\n", name);
		CLOSE
	}
}
void Find2(char *path, char *name, int *flag) {
	char findpath[1000]; //临时地址
	DIR *dir;
	char newpath[1000];
	struct dirent *ptr;
	dir = opendir(path);
	if (dir != NULL) {
		while ((ptr = readdir(dir)) != NULL) {
			if (ptr->d_type == 4 && strcmp(ptr->d_name, ".") != 0
					&& strcmp(ptr->d_name, "..") != 0) //非本身和父级的目录
							{
				if (strcmp(ptr->d_name, name) == 0) //筛选出符合条件的目录
						{
					strcpy(findpath, path); //复制到临时地址
					if (findpath[strlen(findpath) - 1] == '/') //判断地址格式
							{
						strcat(findpath, ptr->d_name);
					} else {
						strcat(findpath, "/");
						strcat(findpath, ptr->d_name);
					}
					YELLOW
					LIGHT
					printf("%s\n", findpath); //打印绝对地址
					CLOSE
					(*flag)++;
				}
				if (path[strlen(path) - 1] == '/') {
					sprintf(newpath, "%s%s", path, ptr->d_name);
				} else {
					sprintf(newpath, "%s/%s", path, ptr->d_name);
				}
				Find2(newpath, name, flag); //递归循环
			} else if (strcmp(ptr->d_name, ".") != 0
					&& strcmp(ptr->d_name, "..") != 0
					&& strcmp(ptr->d_name, name) == 0) //筛选出同名文件
							{
				strcpy(findpath, path);
				if (findpath[strlen(findpath) - 1] == '/') {
					strcat(findpath, ptr->d_name);
				} else {
					sprintf(findpath, "%s/%s", findpath, ptr->d_name);
				}
				BLUE
				LIGHT
				printf("%s\n", findpath);
				CLOSE
				(*flag)++;
			}

		}
		closedir(dir);
	} else {
		RED
		LIGHT
		printf("打开路径失败,请检查权限 ");
		CLOSE
	}
}
void Helps() {
	char order[100];
	PrintfAll();
	printf("输入指令名可查看相关帮助,其他指令退出帮助:");
	fflush(stdin);
	scanf("%s", order);
	getchar();
	if (IsOrder(order)) {
		GREEN
		if (!strcmp(order, "exit")) {
			printf("exit 退出命令解释程序\n");
		}
		if (!strcmp(order, "pwd")) {
			printf("pwd 显示当前所在目录的路径名\n");
		}
		if (!strcmp(order, "help")) {
			printf("help <命令> 查看命令使用帮助\n");
		}
		if (!strcmp(order, "list")) {
			printf("list <目录名> 列出指定目录名中的所有目录及文件\n");
		}
		if (!strcmp(order, "chadir")) {
			printf("chadir <目录名或路径> 改变当前工作目录\n");
		}
		if (!strcmp(order, "makedir")) {
			printf("makedir <目录名> 新建目录\n");
		}
		if (!strcmp(order, "deldir")) {
			printf("deldir <目录名> 删除目录\n");
		}
		if (!strcmp(order, "rename")) {
			printf("rename <旧文件名> <新文件名> 重命名一个文件或目录\n");
		}
		if (!strcmp(order, "copy")) {
			printf("copy <已存在的文件名> <副本文件名或路径> 复制一个已存在的文件\n");
		}
		if (!strcmp(order, "find")) {
			printf("find <目录> <待查找的文件名> 在指定的目录及其子目录中查找指定的文件并输出绝对路径\n");
		}
		CLOSE
	}
}
void PrintfAll() {
	GREEN
	printf("支持的指令有\n");
	printf("(1)pwd\n");
	printf("(2)list\n");
	printf("(3)chadir\n");
	printf("(4)makedir\n");
	printf("(5)deldir\n");
	printf("(6)rename\n");
	printf("(7)copy\n");
	printf("(8)find\n");
	printf("(9)help\n");
	printf("(10)exit\n");
	CLOSE
}
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值