要求
(1)要求实现的基本命令包括:
- pwd //显示当前所在目录的路径名
- list <目录名> //列出指定目录名中的所有目录及文件
- chadir <目录名或路径> //改变当前工作目录
- makedir <目录名> //新建目录
- deldir <目录名> //删除目录
- exit //退出命令解释程序
(2)可选做的扩展命令包括:
- rename <旧文件名> <新文件名> //重命名一个文件或目录
- copy <已存在的文件名> <副本文件名或路径> //复制一个已存在的文件
- find <目录> -name <待查找的文件名> //在指定的目录及其子目录中查找指定的文件,
并输出查找到的文件的绝对路径。
- 设计要求
(1) 设计必须在Linux环境下进行。
(2) 命令解释程序的提示符为:姓名拼音@
(3) 程序编写中不得使用system()系统调用。
(4) 整个程序必须严格经过测试,完成所有基本功能。源程序应有较详尽的注释。
完成情况
pwd
list
chadir
makedir
deldir
rename
copy
find
help
exit
各项基本功能与扩展功能均已完成,
附加帮助功能
附加颜色打印
动态检查命令,实现类似于开发平台检查指令并变换颜色功能
增强错误检查,一定程度上提高了容错率
效果截图
代码
-
程序头文件
<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> 包含获得和使用日期和时间信息的函数的定义 -
宏定义
#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(); 在指定的目录及其子目录中查找指定的文件,并输出查找到的文件的绝对路径。
**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
}