美文网首页
利用IO函数实现ls命令部分功能

利用IO函数实现ls命令部分功能

作者: 静倚晴窗笑此生 | 来源:发表于2019-03-16 16:58 被阅读0次
/* 
 * 实现ls命令部分功能 -l -a -i -h
 * 缺点:不能实现命令组合,如:‘ls -la’;
 */

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <error.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>

#define BUFSIZE 1024

static int is_dir(const char *path);                              //判断是不是目录文件
static void my_stat(const char *path,const char option);          //获取文件属性

void open_dir(const char *path, const char option)                //打开文件
{
    if(!is_dir(path))                                             //不是目录文件直接获取文件属性
    {
        my_stat(path,option);                               
        return ;
    }

    DIR *dp = NULL;
    dp = opendir(path);                                           //获取目录流
    struct dirent *entry = NULL;

    if(dp == NULL)
    {
        perror("opendir()");
        return;
    }

    while(1)
    {
        entry = readdir(dp);
        if(entry == NULL)
        {
            if(error == NULL)
            {
                perror("readdir()");
                closedir(dp);
                return ;
            }
            break;
        }
        if(option == 'a')                     //如果是‘a’选项直接输出目录文件中包含的文件名
            printf("%s\n", entry->d_name);

        else 
            my_stat(entry->d_name, option);    //其它选项将文件路径传给 my_stat 函数
    }
    closedir(dp);
    
    return ;
}

int main(int argc, char *argv[])
{
    char *p = "l::a::i::h::";                    //定义选项
    int opt;

    while((opt = getopt(argc, argv, p)) != -1)   //获取选项
    {
        switch(opt)
        {
            case 'l':                            //以长格式输出文件属性
                if(optarg == NULL)
                    open_dir(".",'l');
                else 
                    open_dir(optarg,'l');
                break;

            case 'a':                            //输出所有文件名
                if(optarg == NULL)               //a后不加参数则读当前目录文件
                    open_dir(".",'a');
                else                             //a后有参数读参数
                    open_dir(optarg,'a');       
                break;

            case 'i':
                if(optarg == NULL)
                    open_dir(".",'i');
                else 
                    open_dir(optarg,'i');
                break;

            case 'h':
                if(optarg == NULL)
                    open_dir(".",'h');
                else 
                    open_dir(optarg,'h');
                break;
            case '?':
                printf("不认识此选项%s\n",argv[optind-1]);
                break;
            case 1:
                printf("非选项参数%s\n",argv[optind-1]);
                break;
            default:
                break;
        }
    }
    return 0;
}

static int is_dir(const char *path)
{
    struct stat cur_stat;

    if(stat(path, &cur_stat) < 0)
    {
        perror("lstat()");
        return -1;
    }
    if(S_ISDIR(cur_stat.st_mode))
        return 1;
    return 0;
}

static void my_stat(const char *path,const char option)
{
    if(option == 'a')
    {
        printf("%s\n",path);
        return ;
    }
    struct stat file_att;

    if(lstat(path, &file_att) == -1)
    {
        perror("lstat()");
        return ;
    }

/********************inode号**************************/
    if(option == 'i')
    {
        printf("%ld  ",file_att.st_ino);
    }


/********************文件类型*************************/

    switch(file_att.st_mode & S_IFMT) 
    {

        case S_IFREG:
            putchar('-');
            break;
        case S_IFDIR:
            putchar('d');
            break;
        case S_IFCHR:
            putchar('c');
            break;
        case S_IFBLK:
            putchar('b');
            break;
        case S_IFIFO:
            putchar('p');
            break;
        case S_IFSOCK:
            putchar('s');
            break;
        case S_IFLNK:
            putchar('l');
            break;
        default:
            break;
    }


/***************文件属性*********************/
    //拥有者
    if(file_att.st_mode & S_IRUSR)
        putchar('r');
    else 
        putchar('-');
    if(file_att.st_mode & S_IWUSR)
        putchar('w');
    else 
        putchar('-');
    if(file_att.st_mode & S_IXUSR)
    {

        if(file_att.st_mode & S_ISUID)
            putchar('s');
        else if(file_att.st_mode & S_ISGID)
            putchar('g');
        else if(file_att.st_mode & S_ISVTX)
            putchar('t');
        else 
            putchar('x');
    }
    else 
        putchar('-');

    //所属组
    if(file_att.st_mode & S_IRGRP)
        putchar('r');
    else 
        putchar('-');
    if(file_att.st_mode & S_IWGRP)
        putchar('w');
    else 
        putchar('-');
    if(file_att.st_mode & S_IXGRP)
        putchar('x');
    else 
        putchar('-');

    //其他
    if(file_att.st_mode & S_IROTH)
        putchar('r');
    else 
        putchar('-');
    if(file_att.st_mode & S_IWOTH)
        putchar('w');
    else 
        putchar('-');
    if(file_att.st_mode & S_IXOTH)
        putchar('x');
    else 
        putchar('-');

/**************硬链接个数***********************/
    printf(" %ld ", file_att.st_nlink);

/**************文件拥有者***********************/
    struct passwd *pwd = NULL;
    pwd = getpwuid(file_att.st_uid);
    printf("%s ",pwd->pw_name);

/**************文件所属组***********************/
    struct group *grp = NULL;
    grp = getgrgid(file_att.st_gid);
    printf("%s ",grp->gr_name);

/**************文件总字节个数*******************/
    if(option == 'l')
        printf("%6ld    ",file_att.st_size);
    if(option == 'h')
        printf("%6ldK   ",file_att.st_blocks/2);

/**************最后修改时间*********************/
    struct tm *tmp = NULL;
    tmp = localtime(&file_att.st_mtim.tv_sec);
    
    char buf[BUFSIZE] = {};
    strftime(buf, BUFSIZE, "%m月 %d %H:%M", tmp);
    printf("%s ",buf);

/**************文件名***************************/
    printf("%s",path);

    printf("\n");

    return ;
}

运行结果:

运行结果

相关文章

网友评论

      本文标题:利用IO函数实现ls命令部分功能

      本文链接:https://www.haomeiwen.com/subject/jhpsmqtx.html