本次课程设计使用C++语言,在Linux发行版系统Ubuntu下编译运行。
在Linux环境下模拟实现简单命令解释器
实现的功能:
- 定义 mypwd 显示当前所在目录的路径名
- 定义 mylist 列出指定目录名中的所有目录及文件
- 定义 mycd 改变当前工作目录
- 定义 mymkdir 新建目录
- 定义 myrmdir 删除目录
- 定义 myexit 退出命令解释程序
- 定义 myrename <旧文件名> <新文件名> 重命名一个文件或目录
- 定义 mycopy <已存在的文件名> <副本文件名或路径> 复制一个已存在的文件
- 定义 myfind <目录> -name <待查找的文件名>
在指定的目录及其子目录中查找指定的文件(输入文件名),并输出查找到的文件的绝对路径。
运行截图
- 主界面
- 显示当前所在目录的路径名
- 改变当前工作目录
- 列出指定目录中的所有目录及文件
- 新建目录
- 删除目录
- 重命名一个文件或目录
- 复制一个已存在的文件
- 在指定的目录及其子目录中查找指定的文件(输入文件名),并输出查找到的文件的绝对路径。
- 退出系统
代码
#include <iostream>
#include <stdio.h>
#include <unistd.h> //mypwd
#include <sstream>
#include <string.h>
#include <dirent.h> //mylist
#include <sys/types.h>
#include <sys/stat.h>
#include <ftw.h>
using namespace std;
string str; //输入的命令
string mingling[1000]; //保存命令
int i; //命令长度
// mypwd --- pwd 显示当前所在目录的路径名
void mypwd()
{
char mypwd[100];
getcwd(mypwd, sizeof(mypwd));
// getcwd()会将当前工作目录的绝对路径复制到参数mypwd所指的内存空间中
cout << mypwd << endl;
}
// mylsit ---list 列出指定目录名中的所有目录及文件
void mylist()
{
//判断命令长度
if (i == 1)
{
cout << "mylist : 在后面缺少了要操作的目录" << endl;
}
else if (i == 2)
{
char temp[80];
strcpy(temp, mingling[1].c_str()); //string转char
DIR *dir = NULL;
//opendir()用来打开参数name 指定的目录, 并返回DIR*形态的目录流, 和open()类似, 接下来对目录的读取和搜索都要使用此返回值.
struct dirent *end;
int j = 0; //逢6换行
// 通过目录名,调用opendir()打开目录流
if ((dir = opendir(temp)) != NULL)
{
/* code */
// 调用readdir()函数读取目录,返回dirent*数据结构
while (end = readdir(dir))
{
j++;
/* code */
// 将d_name(目录名/文件名)输出
if (strcmp(end->d_name, "..") != 0 && strcmp(end->d_name, ".") != 0)
{
cout << end->d_name << " ";
}
if (j % 10 == 0)
{
cout << endl;
}
}
cout << endl;
}
else
{
/* code */
cout << "没有这个文件或目录" << endl;
}
closedir(dir); //关闭流
}
}
// mycd --- cd 改变当前工作目录
void mycd()
{
if (i > 2)
{
cout << "-bash : cd : 参数太多" << endl;
}
else
{
char temp[200]; //保存当前目录
char temp1[200]; //临时目录
getcwd(temp, sizeof(temp));
//如果单纯只有cd命令,返回上一个路径
//格式为cd *** ,目录进入到
if (i == 1)
{
/* code */
char *index = strrchr(temp, '/'); //获取字符在指定字符串中从右面开始的第一次出现的位置index - temp
strncpy(temp1, temp, index - temp); //strncpy()将 temp 中从第0个字符开始复制index - temp个字符给 temp1
int result = chdir(temp1); //改变当前目录路径
if (result != 0)
{
printf("没有这个文件或目录\n");
}
}
if (i == 2) //判断目录是否存在
{
DIR *dir = NULL;
//拼接目录
strcat(temp, "/");
strcat(temp, mingling[1].c_str());
// 通过目录名,调用opendir()打开目录流
if ((dir = opendir(temp)) != NULL)
{
chdir(temp); //存在该目录,改变为此目录
}
else
{
/* code */
cout << "-bash : cd : " << mingling[1] << " : 没有那个文件或目录" << endl;
}
closedir(dir); //关闭目录流
}
}
}
// mymkdir --- mkdir 新建目录
void mymkdir()
{
int index = 0;
/* code */
index = mkdir(mingling[1].c_str(), 0777);
if (index != 0)
{
printf("无法创建目录“%s”:文件已存在\n", mingling[1].c_str());
}
}
// myrmdir --- rmdir 删除目录
void myrmdir()
{
int index = 0;
/* code */
index = rmdir(mingling[1].c_str());
if (index != 0)
{
printf("删除“%s”失败:没有那个目录或目录不为空\n", mingling[1].c_str());
}
}
// myrename --- rename 重命名一个文件或目录
void myrename()
{
int index = 0;
index = rename(mingling[1].c_str(), mingling[2].c_str());
if (index != 0)
{
printf("无法获取“%s”的文件状态:没有那个文件和目录\n", mingling[1].c_str());
}
}
// mycopy --- copy <已存在的文件名> <副本文件名或路径> 复制一个已存在的文件
void mycopy()
{
if (i > 3)
{
cout << "-bash : mycopy : 参数太多" << endl;
}
if (i == 1 || i == 2)
{
cout << "mycopy : 在后面缺少了要操作的目录或文件" << endl;
}
else if (i == 3)
{
FILE *fp = NULL; //源文件
FILE *fp1 = NULL; //复制文件
char temp[200]; //复制生成文件的目录路径
//判断路径
DIR *dir = NULL;
strcpy(temp, mingling[2].c_str());
fp = fopen(mingling[1].c_str(), "r");
//如果第二个字段是路径
if ((dir = opendir(temp)) != NULL)
{
chdir(temp); //存在该目录,改变为此目录
fp1 = fopen(mingling[1].c_str(), "a"); //路径
}
else
{
/* code */
//copy <已存在的文件名> <副本文件名>
fp1 = fopen(mingling[2].c_str(), "a"); //副本文件名
}
char buff[255];
while (!feof(fp)) //判断文件内容是否为空
{
/* code */
fgets(buff, 255, fp); //读取文件
fputs(buff, fp1); //写入文件
}
fclose(fp); //关闭文件
fclose(fp1);
}
}
// myfind --- 具有 find <目录> -name <待查找的文件名> 在指定的目录及其子目录中查找指定的文件(输入文件名),并输出查找到的文件的绝对路径。
int fn(const char *file, const struct stat *sb, int flag)
{
string temp1; //存放绝对路径
if (flag == FTW_F) //是文件
{
temp1 = file;
char temp2[100]; //存放文件名
strcpy(temp2, temp1.c_str());
char *index = strrchr(temp2, '/'); //获取字符在指定字符串中从右面开始的第一次出现的位置index - temp
//判断待查找的文件名存在,输出绝对路径
if (strcmp(mingling[3].c_str(), temp1.substr(index - temp2 + 1, temp1.size()).c_str()) == 0)
{
cout << file << endl;
}
}
return 0;
}
void myfind()
{
//判断目录是否存在
DIR *dir = NULL;
if (i != 4)
{
cout << "命令配套不完整" << endl;
return;
}
if ((dir = opendir(mingling[1].c_str())) == NULL)
{
cout << "-bash : myfind : " << mingling[1] << " : 没有那个文件或目录" << endl;
}
else
{
/* code */
ftw(mingling[1].c_str(), fn, 500);
}
}
//所完成的命令模拟
void menu()
{
cout << endl;
cout << " ****在Linux环境下模拟实现简单命令解释器****" << endl;
cout << " 定义 mypwd 显示当前所在目录的路径名" << endl;
cout << " 定义 mylist 列出指定目录名中的所有目录及文件" << endl;
cout << " 定义 mycd 改变当前工作目录" << endl;
cout << " 定义 mymkdir 新建目录" << endl;
cout << " 定义 myrmdir 删除目录" << endl;
cout << " 定义 myexit 退出命令解释程序" << endl;
cout << " 定义 myrename <旧文件名> <新文件名> 重命名一个文件或目录" << endl;
cout << " 定义 mycopy <已存在的文件名> <副本文件名或路径> 复制一个已存在的文件" << endl;
cout << " 定义 myfind <目录> -name <待查找的文件名> 在指定的目录及其子目录中查找指定的文件(输入文件名),并输出查找到的文件的绝对路径。" << endl;
cout << " ****************************************" << endl
<< endl;
}
//输入命令
void input()
{
//模拟器标签
char local[100] = " ~ ";
char temp11[100];
getcwd(temp11, sizeof(temp11));
strcat(local, temp11);
strcat(local, " > ");
cout << local;
getline(cin, str);
//解析命令
istringstream is(str); //头文件#include<sstream> 将string字符串按空格分开并分别保存
string temp; //临时变量
for (i = 0; is >> temp; i++)
{
mingling[i] = temp;
}
}
int main()
{
menu();
input();
for (;;) //判断命令是否退出
{
if (strcmp(mingling[0].c_str(), "mypwd") == 0)
{
mypwd();
}
else if (strcmp(mingling[0].c_str(), "mylist") == 0)
{
mylist();
}
else if (strcmp(mingling[0].c_str(), "mycd") == 0)
{
mycd();
}
else if (strcmp(mingling[0].c_str(), "mymkdir") == 0)
{
mymkdir();
}
else if (strcmp(mingling[0].c_str(), "myrmdir") == 0)
{
myrmdir();
}
else if (strcmp(mingling[0].c_str(), "myexit") == 0)
{
_exit(0);
}
else if (strcmp(mingling[0].c_str(), "myrename") == 0)
{
myrename();
}
else if (strcmp(mingling[0].c_str(), "mycopy") == 0)
{
mycopy();
}
else if (strcmp(mingling[0].c_str(), "myfind") == 0)
{
myfind();
}
else
{
cout << "命令出错" << endl;
}
memset(mingling, 0, 200); //清除string数组
input();
}
return 0;
}