一、实现的命令及功能
- ls命令(实际上实现的是ls -l命令)
- echo
- cat
- mkdir
- rm
- cd
- pwd
- cp
- wc
- rmdir
- 输入输出重定向
- 管道
二、分模块讲解
1.用到的所有头文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pwd.h>
#include <grp.h>
#include<wait.h>
#include <time.h> //解析文件的时间属性
#include <dirent.h> //打开目录,读目录,关目录
2.ls命令(实际上实现的是ls -l命令)
(1)实现功能
打印输出当前目录下的所有目录和文件的属性
(2)步骤
1)需要找到该路径下所有目录和文件的名字
2)找到当前路径,需要头文件#include<unistd.h>,调用函数getcwd():
char basePath[100];
getcwd(basePath,sizeof(basePath));
将得到的当前路径放在basePath里
3)在当前路径下找到所有文件、目录的名字
用到的头文件:#include <dirent.h>
用到的结构体:
DIR *dir; //目录指针指向当前目录
struct dirent *ptr; //循环指向每一个文件。
用opendir(绝对路径)函数打开当前目录,用readdir(目录指针dir)函数,循环读取每一个文件和目录的名字;最后用closedir(目录指针dir)函数关闭目录
4)调用stat函数,使用上一步得到的文件(目录)名作为参数,可以得到一系列的文件属性。
用到的头文件:#include <sys/types.h>、 #include <sys/stat.h> 、#include <unistd.h>
用到的结构体
struct stat info; //文件(目录)的属性信息
用到的函数:
stat(filename,&info); //将文件filename的以下各种属性存放在info中
5)stat结构体种只包含了部分ls命令列出来的文件属性,如st_mode、st_size等,可以直接打印出来。例如,st_mode不需要解析。
6)文件的其他的属性需要调用更底层的函数进行进一步的解析。
• getpwuid函数:解码所有者信息(解析struct stat中的st_uid数据)
struct passwd *pswd;
pswd=getpwuid(info.st_uid);
• getgrgid函数:解码所属组信息(解析struct stat中的 st_gid数据)
struct group *grp;
grp=getgrgid(info.st_gid);
• localtime函数:解码上次访问时间信息 (解析struct stat中的 st_atime数据)
struct tm *atime;
atime = localtime(&info.st_mtime);
(3)完整代码
/*
实现ls命令
用法:ls
*/
void ls(){
DIR *dir;
struct dirent *ptr;
//得到绝对路径
char basePath[100];
getcwd(basePath,sizeof(basePath)); //get当前路径 ,放在basePath里
if ((dir=opendir(basePath)) == NULL)
{
perror("Open dir error...");
exit(1);
}
while ((ptr=readdir(dir)) != NULL)
{
if(strcmp(ptr->d_name,".")==0 || strcmp(ptr->d_name,"..")==0) ///current dir OR parrent dir
continue;
else if(ptr->d_type == 8) ///file
//printf("%s\n",ptr->d_name);
lsCore(ptr->d_name);
else if(ptr->d_type == 10) ///link file
//printf("%s\n",ptr->d_name);
lsCore(ptr->d_name);
else if(ptr->d_type == 4) ///dir
{
//printf("%s\n",ptr->d_name);
lsCore(ptr->d_name);
}
}
closedir(dir);
}
/*
本函数实现ls命令的核心功能;从ls函数中得到文件名,打印文件属性
*/
void lsCore(char *filename){
struct stat info;
stat(filename,&info);
/*-----打印类型,权限----*/
switch(info.st_mode & S_IFMT)
{
case S_IFREG:printf("-");break;
case S_IFDIR:printf("d");break;
case S_IFLNK:printf("l");break;
case S_IFCHR:printf("c");break;
case S_IFBLK:printf("b");break;
case S_IFIFO:printf("p");break;
case S_IFSOCK:printf("s");break;
}
char rwx[]={
'r','w','x'};
for(int i=0; i<10; i++)
{
printf("%c",info.st_mode & (0400>>i) ? rwx[i%3] : '-');
}
/*-----打印所有者 ----*/
struct passwd *pswd;
pswd=getpwuid(info.st_uid);
printf(" %s",pswd->pw_name);
/*-----所属组----*/
struct group *grp;
grp=getgrgid(info.st_gid);
printf(" %s",grp->gr_name);
/*-----打印文件大小----*/
printf(" %ld ",info.st_size);
/*-----打印最近时间 ----*/
struct tm *atime;
atime = localtime(&info.st_mtime);
printf("%d-%d-%d %d:%d "
,atime->tm_year+1900
,atime->tm_mon+1,atime->tm_mday
,atime->tm_hour,atime->tm_min);
/*-----打印文件名----*/
printf(" %s\n",filename);
}
3.echo
/*
实现echo函数
实现功能:回显echo命令的参数
用法:echo hello dad!
*/
void echo(char *argv[]){
int i=1;
while(argv[i]!=NULL){
printf("%s ",argv[i]);
i++;
}
printf("\n");
}
4.cat
/*
实现cat函数
实现功能:对文件1.txt内容进行标准输出
用法:cat 1.txt 或 cat /home/zxf/1.txt
*/
void cat(char *argv[]){
char buf[200]; //模拟缓冲区
int fp;
fp=open<