C语言实现Linux之ls

ls命令用来显示目标列表。

 

常用参数:

-l    :以长格式显示目录下的内容列表。输出信息从左向右依次包括文件名,文件类型,权限模式,硬连接数,所有者、组、文件大小和文件的最后修改时间等;

-a   :显示所有档案及目录;

-r    :以文件名反序排列并输出目录内容列表;

-t    :用文件和目录的更改时间排序;

-R   :递归处理,将指定目录下的所有文件及子目录一并处理。

常用参数组合:

ls –rtl:反向按时间排序,查看一个目录下最近修改的文件。

ls –full-time:在写shell脚本的时候需要获取文件被更新的时间,此命令可以获取时间细微的变化。

获取指定目录下文件名:

/*
ls_name.c
*/
#include<stdio.h>
#include<sys/types.h>
#include<dirent.h>

void do_ls(char[]);

int main(int argc, char **argv)
{
    if (argc == 1)
    {
        do_ls(".");
    }
    else
    {
        while(--argc)
        {
            printf("%s:
",*++argv);
            do_ls(*argv);
        }
    }

    return 0;
}


void do_ls(char dirname[])
{
    DIR* dir_ptr;
    struct dirent *direntp;

    if ((dir_ptr = opendir(dirname)) == NULL)
    {
        fprintf(stderr, "ls1: cannot open %s
",dirname);
    }
    else
    {
        while((direntp = readdir(dir_ptr)) != NULL) 
        {
            //printf("direntp->d_name = %s
",direntp->d_name);
            if(    strcmp(direntp->d_name, ".") != 0 &&
                strcmp(direntp->d_name, "..") != 0)
            printf("%s
", direntp->d_name);
        }
        close(dir_ptr);
    }
}

运行结果:

获取指定文件详细信息:

/*
ls_fileinfo.c
*/
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>

void show_stat_info(char *filename, struct stat *buf)
{
    printf("mode		:%o
", buf->st_mode);
    printf("linkers		:%d
",(int)buf->st_nlink);
    printf("user		:%d
", buf->st_uid);
    printf("group_id	:%d
", buf->st_gid);
    printf("size		:%d
", (int)buf->st_size);
    printf("modtime		:%d
", (int)buf->st_mtime);
    printf("group_name	:%s
", filename);
}

int main(int argc, char **argv)
{
    struct stat info;

    if (argc > 1)
    {
        if (stat(argv[1], &info) != -1)
        {
            show_stat_info(argv[1], &info);
        }
        else
        {
            perror(argv[1]);
        }
    }

    return 0;
}

运行结果:

Linux下对于不同用户的权限展示,分别是用户、用户组、所在组在stat结构体中的mode这个字段进行存储。

mode字符是一个16位的二进制数,前4位用作文件类型,1代表具有某个属性,0代表没有。

接下来的三位分别为user-ID,set-group-ID和sticky位,最后9位是许可权限,分三组,每组3位。

这里使用掩码的技术来划分,就跟ip中的子网掩码一样把2进制的1000000110110110划分为1,000,000,110,110,110,从而得到8进制的100664

对二进制进行位与操作,就是所谓的解码。例如判断目录的代码如下:

if ((info.st_mode & 0170000) == 0040000)
{
    printf(“this is a directory”);
}

用宏定义代替以上代码:

#define S_ISFIFO(m)  (((m)&(0170000))==(0040000))
#define S_ISDIR(m)  (((m)&(0170000))==(0020000))
#define S_ISCHR(m)  (((m)&(0170000))==(0060000))
#define S_ISBLK(m)  (((m)&(0170000))==(0100000))
if(S_ISDIR(info.st_mode))
{
    printf("this is a directory");
}

获取指定目录下详细文件信息

/*
ls_fin.c
*/
#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<dirent.h>
#include<sys/stat.h>
#include<grp.h>
#include<pwd.h>

void do_ls(char []);
void dostat(char *);
void show_file_info(char *, struct stat *);
void mode_to_letters(int mode, char str[]);
char *uid_to_name(uid_t uid);
char *gid_to_name(gid_t gid);


int main(int argc, char **argv)
{
    if (argc == 1)
    {
        do_ls(".");
    }    
    else
    {
        while (--argc)
        {
            printf("%s:
", *++argv);
            do_ls(*argv);
        }
    }

    return 0;
}

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);
        }
        closedir(dir_ptr);
    }
}

void dostat(char *filename)
{
    struct stat info;
    if (stat(filename, &info) == -1)
    {
        perror(filename);
    }
    else
    {
        show_file_info(filename, &info);
    }
}

void show_file_info(char *filename, struct stat *info_p)
{
    char *uid_to_name(), *ctime(), *gid_to_name();
    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;
    }
}

运行结果:

原文地址:https://www.cnblogs.com/wanghao-boke/p/11959330.html