改变当前工作目录,支持相对路径、绝对路径,支持~
开头替代/home/username
-
命令格式
cd /path/to/directory/
逐个字节比较两个文件,并输出第一不同字节所在的位置和行数
-
命令格式
cmp file1 file2
链接文件并输出连接后文件内容
- 命令格式
cat files
统计文件,并输出统计内容(默认输出行数、字节数、单词数)
结果与参数给出顺序无关
- 命令格式
wc [option]... file[s]
- 参数
- -l: 行数
- -c: 字节数
- -w: 单词数
复制文件(夹)
- 命令格式
cp file TargetFile
cp [option] file[s] ... folder[s] TargetFolder
- 参数
- -r: 复制内容包含文件夹
输出用户手册
- 命令格式
man command[s]
用户可以编写.sh
文件
sh /path/to/sh/xxx.sh
即可
安装或卸载(使用option -d)已经提供原文件或*.o
文件的命令
- 命令格式
install [option] command[s]
-
参数
-d: 后跟要卸载的命令
install命令通过调用system("make")
编译新命令并重新链接实现增加新命令或删除旧命令
- myTerm中通过
system("./myShell)
启动myShell - myShell中读取命令并根据命令是否已经被install决定是否分配给cmdManager
- cmdManager收到分配后,调用相应的命令(每个命令为一个类,都继承自Command基类)
- ./files/config.txt 中记录已经install的命令
- ./files/manuals/*.man为各个命令同名的帮助文档
- ./source下存放所有源文件
- ./bin下存放所有.o文件
- ./makefile中进行除myTerm模块以外的所有编译
- cmdManager调用install
- install检查用户给出的参数中的命令是否已经被安装,以及是否在./source目录下有对应的源文件,未安装且有源文件的加入一个set中
- 改写config.txt,加入新命令
- 改写cmdManager,加入对新命令调用的代码段
- 改写makefile,加入对新命令的编译和链接
- 调用
system("make")
重新编译myShell exit(1)
退出当前myShell
myTerm
收到返回值后重新system("myShell")
重启myShell
myShell提供cmdManager.h/.cpp
来调用命令,调用命令的代码为
if(cmd == string("myCommand"))
myCommand tmp(argv);
即命令的调用通过创建临时变量完成。其中argv
为命令行中除去命令名的部分,该分割在myShell.h/.cpp
中完成,不需要重新设计。
开发一个新的命令,开发者需要:
-
设计一个类,包含同名.h,.cpp文件,并存放到./source目录下
-
该类的构造函数
myCommand(string argv);
-
并在构造函数中完成所有命令操作。
开发者也可以借助Command
类作为基类对命令进行开发,
- Command中提供的API
class Command{ //Base
protected:
vector<string> option;
vector<vector<string>> args;
enum type{_file_,_dir_,_null_};
type filetype(string file);
public:
Command(string input);
virtual ~Command();
virtual int check_init()=0;
virtual void print_error(char*error_type,string args)=0;
};
在Command的构造函数中,将完成命令行的分割并存储到options和args中
例如:
cmd file1 file2 -abc file3 file4 -e file5
将得到:
option[0]="",args[0]={"file1","file2"}
option[1]="abc",args[1]={"file3","file4"}
option[2]="e", args[2]={"file5"}
- 开发者需要在派生类中根据命令的参数及其意义,重定义
check_init
和paint_error
#include"Command.h"
class myCommand:public Command{
public:
myCommand(string input);
int check_init();
void print_error(char * error_type, string args);
};
- 一般来说,建议
myCommand(string input)
按如下格式定义
myCommand::myCommand(string input)
:Command(input){
if(!check_init())
cout<<"myCommand: type man myCommand for help"<<endl;
else{
//your
//code
//here
}
}
- demo.h
#include"Command.h"
using namespace std;
class demo:public Command{
public:
demo(string input);
~demo();
int check_init();
void print_error(char* error_type,string argv);
};
-
demo.cpp
#include"demo.h" #include<iostream> demo::demo(string input) :Command(input){ if(check_init()) for(int i=0;i<args[0].size();i++) cout<<args[0][i]<<endl; else cout<<"Please type man demo for help"<<endl; } demo::~demo(){ cout<<"This is the destructor of demo!"<<endl; } int demo::check_init(){ cout<<"this is check_init()"<<endl; cout<<"suppose that you have enter a wrong argument."<<endl; cout<<"demo: let's call print_error"<<endl; print_error((char*)"option",option[0]); } void demo::print_error(char *error_type,string argv){ string error = string(error_type); cout<<"demo: this is print_error()"<<endl; cout<<"demo: error of "<<error<<". It happens because"<<argv<<endl; }
将
demo.h
和demo.cpp
存放在./source
目录下运行myTerm启动终端和myShell
安装demo:
install demo
卸载demo:
也可以同时安装、卸载多个命令
将通过system(CommandLine)
调用系统的Shell运行。