操作系统大作业:在Linux环境下模拟实现简单命令解释器(文档部分)

一、   课程设计(大作业)具体内容

3.1 程序概述

已完成一下命令

pwd                  //显示当前所在目录的路径名

list  <目录名>          //列出指定目录名中的所有目录及文件

modifydir  <目录名或路径>   //改变当前工作目录

makedir  <目录名   //新建目录

deldir  <目录名>      //删除目录

exit                 //退出命令解释程序

rename  <旧文件名> <新文件名>  //重命名一个文件或目录

copy  <已存在的文件名> <副本文件名或路径>  //复制一个已存在的文件

date  //显示当前日期

 

3.2 概念原理

1. 命令行解析:首先,需要从用户输入中解析出命令和其对应的参数。这可以通过使用Linux的`read`函数读取用户输入,然后使用正则表达式或其他方法解析出命令和参数。

 

2. 命令处理:根据解析出的命令,调用相应的系统函数来实现对应的功能。例如,`pwd`命令可以通过调用`getcwd`函数来实现,`list`命令可以通过调用`listdir`函数来实现。

 

3. 目录操作:在处理目录相关命令(如`modifydir`、`makedir`、`deldir`)时,需要掌握Linux目录结构的原理,了解`chdir`、`mkdir`、`rmdir`等系统调用。

 

4. 文件操作:处理文件相关命令(如`rename`、`copy`)时,需要了解文件操作的基本原理,如文件权限、文件描述符等,并使用相应的系统调用(如`rename`、`cp`)来实现。

 

5. 文件查找:实现`find`命令时,需要使用`find`命令的语法规则,结合Linux的文件系统实现查找功能。

 

6. 错误处理:在程序运行过程中,可能会遇到各种错误,如输入解析错误、目录操作错误等。需要使用错误处理机制,如`perror`函数,来输出错误信息,提示用户正确操作。

 

7. 程序循环:使用`while`循环不断接收用户输入,直到用户输入`exit`命令为止。

 

8. 输出格式:按照题目要求,输出提示符为“姓名拼音@”,需要在程序中设置好输出格式。

 

9. 测试与注释:在编写程序的过程中,要注重测试每一个功能,确保其正常运行。同时,为代码添加详细的注释,方便他人理解和维护。

 

总体来说,实现这个简单命令解释器需要掌握Linux系统调用、文件操作、正则表达式解析、错误处理等基本概念和原理。在编写过程中,要注重代码的结构和可读性,确保程序稳定可靠。

 

3.3 完成情况

 

已完成以下命令

1.pwd                  //显示当前所在目录的路径名

2.list  <目录名>          //列出指定目录名中的所有目录及文件

3.modifydir  <目录名或路径>   //改变当前工作目录

4.makedir  <目录名   //新建目录

5.deldir  <目录名>      //删除目录

6.exit                 //退出命令解释程序

   7.rename  <旧文件名> <新文件名>  //重命名一个文件或目录

   8.copy  <已存在的文件名> <副本文件名或路径>  //复制一个已存在的文件

9.date  //显示当前日期

其中find功能未实现

 

 

 

                                              3-1

3.4 详细设计

3.4.1. pwd

//显示当前所在目录的路径名  mypwd

void mypwd() {

    char path[100];

    getcwd(path,100);

    cout<<"当前目录: "<<path<<endl;

}

使用getcwd函数获取当前目录的路径,将其存储在path数组中。getcwd函数默认返回的是当前工作目录的路径,而不是当前运行目录的路径。

 

3.4.2. list

bool mylist(string dir) {

    DIR* d = opendir(dir.c_str());

    if(d==NULL) {

        return false;

    } else {

    struct dirent *dirent;

        while(dirent=readdir(d)) {

        cout<<endl;

        cout<<"  "<<dirent->d_name<<"  "<<dirent->d_type<<"  "<<dirent->d_reclen<<endl;

        cout<<endl;

    }

    closedir(d);

        return true;

    }

}

1. 调用`opendir(dir.c_str())`打开指定的目录。`DIR* d`是一个指向打开目录的指针。

2. 如果打开目录失败(`d==NULL`),函数返回false,表示目录不存在或无法访问。

3. 否则,循环遍历目录下的所有文件和子目录。`dirent`是一个结构体指针,用于存储目录项的信息。

4. 使用`readdir(d)`从目录中读取下一个目录项。

5. 输出目录项的名称(`dirent->d_name`)、类型(`dirent->d_type`)和大小(`dirent->d_reclen`)。

6. 使用`closedir(d)`关闭目录。

7. 循环结束后,函数返回true,表示目录遍历成功。

 

3.4.3. modifydir

// 改变当前目录-mycd

bool mycd(string path) {

    if(chdir(path.c_str())==0) {

        return true;

    } else {

        return false;

    }

}

函数内部使用系统调用函数 chdir() 来实现改变当前目录的功能。chdir() 函数接收一个字符串参数,表示要切换到的目录路径。

 

如果 chdir() 函数执行成功(返回值为 0),说明目录切换成功,函数返回 true。否则,返回 false

 

3.4.4.makedir

//新建目录-mymkdir

bool mymkdir(string dir) {

    if(mkdir(dir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)==0) {

        return true;

    } else {

        return false;

    }

}

 

1. 使用`mkdir`函数尝试创建目录。`mkdir`函数的原型为:`int mkdir(const char *pathname, mode_t mode)`其中`pathname`为要创建的目录路径,`mode`为权限模式。

 

2. `mkdir`函数传入的`dir.c_str()`,即将目录名称转换为字符串的C风格字符指针。

 

3. 设置权限模式`S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH`,表示允许用户(U)、组(G)、其他(O)和所有(A)具有读、写、执行权限。

 

4. 检查`mkdir`函数的返回值。如果返回值为0,表示目录创建成功,函数返回true;否则,返回false

 

总之,这段代码的功能是尝试创建一个名为`dir`的目录,如果创建成功,返回true,否则返回false

 

3.4.5. deldir

//删除目录-myrmdir

bool myrmdir(string dir) {

    if(rmdir(dir.c_str())==0) {

        return true;

    } else {

        return false;

    }

}

1. 使用`if`语句检查`rmdir`函数的返回值。如果返回值为0,表示目录删除成功,函数返回true

2. 如果目录删除失败,函数返回false

 

3.4.6. exit

Return 0;直接退出

3.4.7. rename

//重命名文件或目录-myrename

bool myrename(string lastname,string newname) {

    if(rename(lastname.c_str(),newname.c_str())==0) {

        return true;

    } else {

        return false;

    }

}

该函数接受两个参数,一个是旧文件名(lastname),另一个是新文件名(newname)。函数使用系统调用rename()来执行重命名操作。

 

3.4.8. copy

//复制文件-mycopy

//先判断文件是否存在,存在则在原来要复制的文件名后加(1),否则直接复制

bool mycopy(string existname,string newname) {

    int fo1,fo2;

    char buf[1024];

    fo1=open(existname.c_str(),O_RDONLY);

    if(fo1==-1) {  

    return false;

    } else {

    fo2=open(newname.c_str(),O_RDONLY);

    if(fo2!=-1) {

        int i;

        cout<<"确定替换文件?"<<endl;

        cout<<"输入1为确定,1为否定.";

        cin>>i;

        if(i!=1) {

        newname+="(1)";

        }

        close(fo2);

    }

    fo2=open(newname.c_str(),O_WRONLY|O_CREAT,S_IRWXU);

    int size = read(fo1,buf,sizeof(buf));

    write(fo2,buf,size);

    close(fo1);

    close(fo2);

    return true;

    }

}

1. 首先,检查源文件是否存在。如果存在,则在原文件名后加(1),否则直接复制。

2. 打开源文件(existname)以只读模式,如果打开失败,返回false

3. 尝试以只读模式打开目标文件(newname),如果打开成功,但不替换文件,关闭文件并提示用户确定是否替换。

4. 如果用户输入1,则在目标文件名后加(1),否则不加。

5. 以写入和创建模式打开目标文件(newname),读取源文件的内容,并将数据写入目标文件。

6. 关闭源文件和目标文件,返回true表示复制成功。

 

3.4.9. date

//显示当前日期-mydate

void date()

{

  time_t timeval;

  (void)time(&timeval);

  string timestr;

  // invoke the ctime fuction and return the string

  timestr = ctime(&timeval);

  cout<<"当前时间: "<<timestr<<endl;

}

 

1. 定义一个时间类型(time_t)的变量timeval,用于存储时间戳。

2. 使用time函数获取当前时间,并将时间戳存储在timeval变量中。注意,这里的time函数调用不需要传入参数,因为它默认使用本地时间。

3. 定义一个空字符串timestr,用于存储转换后的时间字符串。

4. 使用ctime函数将时间戳转换为字符串,并将结果存储在timestr中。ctime函数将时间戳转换为UTC时间,并使用默认的格式字符串("%Y-%m-%d %H:%M:%S")输出。

5. 使用cout输出转换后的时间字符串,并在末尾添加换行符。

 

3.5 系统测试

 

                                                    3-2️ 编辑.c文件

 

                                                     3-3 编译并运行

 

                                           3-4 输入tanghan@pwd

 

 

 

3-5 输入tanghan@list

 

3-6 tanghan@list 输出结果

 

                                          3-7 输入tanghan@modifydir

 

 

 

3-8 输入tanghan@makedir

 

 

 

3-9 新建目录成功

 

 

                                          3-10 输入tanghan@deldir

 

 

3-11 成功删除

 

 

                                          3-12 删除成功

 

 

                                          3-13 输入tanghan@exit

 

 

                                          3-14 输入tanghan@rename

 

                                          3-15 改名成功

                                          3-16 输入tanghan@date显示日期成功

 

二、   总结

4.1  遇到的困难及解决的问题

 

4.2  总结与感想

 

三、   参考文献

[1] 鲍勃·泰勒(Bob Taylor),《Linux命令行与Shell脚本编程大全》(Linux Command Line and Shell Scripting),人民邮电出版社,2016年。

 

[2] 埃里克·瑞姆(Eric Raymond),《Linux编程指南》(The Linux Programming Interface),机械工业出版社,2014年。

 

[3] 尼尔·哈丁(Neil Haddad),《Linux命令行与Shell脚本编程从入门到精通》(Linux Command Line and Shell Scripting Boot Camp),电子工业出版社,2019年。

 

[4] 迈克尔·瓦尔(Michael Wale),《Linux命令行与Shell脚本编程实战》(Linux Command Line and Shell Scripting in Action),人民邮电出版社,2017年。

posted @ 2023-12-25 18:55  养肥胖虎  阅读(48)  评论(0编辑  收藏  举报