zoukankan      html  css  js  c++  java
  • 用C++实现Linux中shell的ls功能

     实现输出当前目录下的文件名

    ls功能:

    方法一:

    #include <iostream>
    #include <algorithm>
    #include <stdio.h>
    #include <stdlib.h>
    #include <dirent.h>
    #include <sys/types.h>
    #include <string.h>
    #include <string>
    using namespace std;
    
    bool cmp( string s1,string s2){
      return s1<s2;
    }
    
    int main()
    {
      DIR *dir;
      char s[100];
      string data[100];
      int tot=0;
      struct dirent *rent;
      dir =opendir(".");
      while(rent=readdir(dir))
      {
          strcpy(s,rent->d_name);
          if(s[0]!='.'){
           data[tot]=s;
          tot++;
          }
      }
      sort(data,data+tot,cmp);
      for(int i=0;i<tot;i++)
       cout<<data[i]<<"  ";
      puts("");
      closedir(dir);
      return 0;
    }

    方法二:

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <string.h>
    #include <errno.h>
    #include <pwd.h>
    #include <grp.h>
    #include <time.h>
    #include <dirent.h>
    int do_ls(char *dir,char *filename,int lflag)
    {
        int n;
        struct stat buf;
        char out[100];
        struct passwd *pw;
        struct group *gr;
        struct tm *t;
        if(lflag == 0) //如果不带l参数,直接显示文件/目录名
        {
            printf("%s	",filename);
            return 0;
        }
        if(lstat(dir,&buf)<0)
        {
            fprintf(stderr,"stat error:%s
    ",strerror(errno));
            return -1;
        }
        switch(buf.st_mode & S_IFMT) //获取字符串的属性:普通文件-、目录d、字符设备c、块设备b、管道文件p、连接文件l、套接字文件s
        {
        case S_IFREG:
            printf("-");
            break;
        case S_IFDIR:
            printf("d");
            break;
        case S_IFCHR:
            printf("c");
            break;
        case S_IFBLK:
            printf("b");
            break;
        case S_IFIFO:
            printf("p");
            break;
        case S_IFLNK:
            printf("l");
            break;
        case S_IFSOCK:
            printf("s");
            break;
        }
        for(n=8; n>=0; n--) //打印文件的读写属性:读r、写w、执行x、无权限-
        {
            if(buf.st_mode&(1<<n))
            {
                switch(n%3)
                {
                case 2:
                    printf("r");
                    break;
                case 1:
                    printf("w");
                    break;
                case 0:
                    printf("x");
                    break;
                default:
                    break;
                }
            }
            else
            {
                printf("-");
            }
        }
        printf(" %d",buf.st_nlink); //硬链接数,此链接非彼链接,指(包含)目录的个数,文件为1,目录起始为2,再加上目录里包含的目录个数(不递归,只一层)
        pw = getpwuid(buf.st_uid); //所属用户名
        printf(" %s",pw->pw_name);
        gr = getgrgid(buf.st_gid); //所属组名
        printf(" %s",gr->gr_name);
        printf(" %ld",buf.st_size); //字节计总大小
        t = localtime(&buf.st_atime); //最后一次访问时间
        printf(" %d-%d-%d %d:%d"
               ,t->tm_year+1900
               ,t->tm_mon+1
               ,t->tm_mday
               ,t->tm_hour
               ,t->tm_min);
        printf(" %s ",filename);
        if(S_ISLNK(buf.st_mode)) //判断是否为链接,是返回真
        {
            printf(" -> ");
            if(readlink(filename,out,100)==-1)
            {
                 //printf("readlink error
    ");
            }
            printf("%s",out);
        }
        printf("
    ");
        return 0;
    }
    int ls_prepare(char *w,int aflag,int lflag) //ls的准备工作
    {
        struct stat buf; //man lstat可以看到此结构
        char name[100];
        DIR *dir; //类似打开文件的fd描述符
        struct dirent *pdr; //man readdir可以看到此结构
        if(lstat(w,&buf)<0) //获取文件/目录属性并赋值给buf,该函数和lstat一样,只是当w为链接时,指代他本身,并不存在文件
        {
            fprintf(stderr,"stat error:%s
    ",strerror(errno));
            return -1;
        }
        if(S_ISDIR(buf.st_mode)) //判断是否为目录,是返回真
        {
            dir = opendir(w); //打开目录
            while ((pdr = readdir(dir))!=NULL) //读/遍历目录
            {
                if(aflag==0) //如果不带a参数,越过以.开头的所有文件/目录
                {
                    if(pdr->d_name[0]=='.')
                        continue;
                    memset(name,0,100);
                    strcpy(name,w); //拷贝
                    strcat(name,"/"); //追加
                    strcat(name,pdr->d_name);
                    do_ls(name,pdr->d_name,lflag);
                }
                else  //有a参数显示所有
                {
                    memset(name,0,100);
                    strcpy(name,w);
                    strcat(name,"/");
                    strcat(name,pdr->d_name);
                    do_ls(name,pdr->d_name,lflag);
                }
            }
            closedir(dir);
        }
        else  //为文件则直接显示
        {
            do_ls(w,w,lflag);
        }
        return 0;
    }
    int main(int argc,char **argv)
    {
        int aflag =0;
        int lflag =0;
        char c;
        int i;
        while((c = getopt(argc,argv,"al"))!=-1) //解析命令行参数,即-/--后面的字符串和给定的字符串匹配,有未解析字母返回字母或问号(取决于第3个参数),否则返回-1
        {
            switch(c) //此处仅匹配a(所有)和l(列表),即只支持参数a、l
            {
            case 'a':
                aflag =1;
                break;
            case 'l':
                lflag =1;
                break;
            default:
                break;
            }
        }
        if(argc == optind ) 
        {
            ls_prepare("./",aflag,lflag);
        }
        else
        {
            for(i=optind; i<argc; i++) //所有目录都传进去
            ls_prepare(argv[i],aflag,lflag);
        }
        printf("
    ");
        return 0;
    }

    ls -l功能:

    #include <stdio.h>
    #include <sys/types.h>
    #include <dirent.h>
    #include <sys/stat.h>
    #include <pwd.h>
    #include <grp.h>
    
    void show_file_info(char* filename, struct stat* info_p) {
     char* uid_to_name(), *ctime(), *gid_to_name(), *filemode();
     void mode_to_letters();
     char modestr[11];
    
     mode_to_letters(info_p->st_mode, modestr);
    
     printf("%s", modestr);
     printf(" %4d", (int) info_p->st_nlink);
     printf(" %-8s", uid_to_name(info_p->st_uid));
     printf(" %-8s", gid_to_name(info_p->st_gid));
     printf(" %8ld", (long) info_p->st_size);
     printf(" %.12s", 4 + ctime(&info_p->st_mtime));
     printf(" %s
    ", filename);
    
    }
    
    void mode_to_letters(int mode, char str[]) {
     strcpy(str, "----------");
    
     if (S_ISDIR(mode)) {
      str[0] = 'd';
     }
    
     if (S_ISCHR(mode)) {
      str[0] = 'c';
     }
    
     if (S_ISBLK(mode)) {
      str[0] = 'b';
     }
    
     if ((mode & S_IRUSR)) {
      str[1] = 'r';
     }
    
     if ((mode & S_IWUSR)) {
      str[2] = 'w';
     }
    
     if ((mode & S_IXUSR)) {
      str[3] = 'x';
     }
    
     if ((mode & S_IRGRP)) {
      str[4] = 'r';
     }
    
     if ((mode & S_IWGRP)) {
      str[5] = 'w';
     }
    
     if ((mode & S_IXGRP)) {
      str[6] = 'x';
     }
    
     if ((mode & S_IROTH)) {
      str[7] = 'r';
     }
    
     if ((mode & S_IWOTH)) {
      str[8] = 'w';
     }
    
     if ((mode & S_IXOTH)) {
      str[9] = 'x';
     }
    }
    
    char* uid_to_name(uid_t uid){
     struct passwd* getpwuid(),* pw_ptr;
     static char numstr[10];
    
     if((pw_ptr = getpwuid(uid)) == NULL){
      sprintf(numstr,"%d",uid);
    
      return numstr;
     }else{
      return pw_ptr->pw_name;
     }
    }
    
    char* gid_to_name(gid_t gid){
     struct group* getgrgid(),* grp_ptr;
     static char numstr[10];
    
     if(( grp_ptr = getgrgid(gid)) == NULL){
      sprintf(numstr,"%d",gid);
      return numstr;
     }else{
      return grp_ptr->gr_name;
     }
    }
    void do_ls(char dirname[]) {
     DIR* dir_ptr;
     struct dirent* direntp;
    
     if ((dir_ptr = opendir(dirname)) == NULL) {
      fprintf(stderr, "ls2: cannot open %s 
    ", dirname);
     } else {
      while ((direntp = readdir(dir_ptr)) != NULL) {
       dostat(direntp->d_name);
      }
    
      close(dir_ptr);
     }
    }
    
    void dostat(char* filename) {
     struct stat info;
    
     if (stat(filename, &info) == -1) {
      perror(filename);
     } else {
      show_file_info(filename, &info);
     }
    }
    
    int main(int ac,char* av[]){
     if(ac == 1){
      do_ls(".");
     }else{
      while(--ac){
       printf("%s: 
    ",*++av);
       do_ls(*av);
      }
     }
    }
    

      

  • 相关阅读:
    oracle日期格式转换 to_date()
    YAML中使用Jinja模板以{{ foo }}开头需要整行加双引号
    linux查看修改线程默认栈空间大小(ulimit -s)
    理解一条语句:SELECT difference(sum("value")) FROM "mq_enqueue" WHERE "channel" =~ /ActiveMQ_TEST/ AND $timeFilter GROUP BY time($interval)
    zookeeper客户端连接报错
    docker swarm join 报错
    redis make报错
    302重定向问题
    svn安装配置
    mysql5.7.22tar包安装
  • 原文地址:https://www.cnblogs.com/chen9510/p/6234611.html
Copyright © 2011-2022 走看看