使用C语言实现ll命令

使用C语言实现ll命令

先来看看执行ll命令后有什么:

[root@localhost day16]# ll
total 44
drwxrwxrwx. 3 root root  4096 May  5 11:38 after
-rwxr-xr-x  1 root root 13072 Aug 16 15:45 a.out
drwxrwxrwx. 3 root root  4096 May  5 11:38 fsx_test_1
drwxrwxrwx. 3 root root  4096 May  5 11:38 fsx_test_2
-rwxrwxrwx. 1 root root  6126 May  5 11:38 ls_res.c
drwxrwxrwx. 2 root root  4096 May  5 11:38 mor
drwxrwxrwx. 3 root root  4096 May  5 11:38 teacher
权限  硬连接 所属用户    所属用户组   大小  创建月份    日期  小时  分钟  文件名

贴总代码:

[root@localhost day16]# cat ls_res.c 
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
#define PATH "./" //做一个宏定义,在预编译阶段,让PATH代替"./"   //这里可以定一个输入参数,就可以指定目录文件了
​
int main(void)
{
    DIR *p_dir = NULL; //定义一个DIR*型指针p_dir 并初始化为空
    p_dir = opendir(PATH); //指针p_dir指向函数opendir(PATH)
    if (NULL == p_dir) //判断是否指向成功
    {
        perror("opendir");
        exit(0);
    }
    char *p_name;//定义一个char*指针p_name,用来存储目录下文件名
    struct dirent *d_dir = NULL;//定义一个readdir函数结构体指针d_dir,并初始化为空
    struct stat st; //定义一个stat函数的对象st
    memset(&st,0,sizeof(st));//清空对象st内存中的垃圾数据
    while (d_dir = readdir(p_dir))//while遍历PATH目录下所有文件,并且d_dir指针绑定readdir(p_dir)函数。注意:每赋值一次,指针跳转一次,这是文件指针
    {
        if ('.' == *(d_dir->d_name))//判断是否为隐藏文件,如果是,则跳过
            continue;
        p_name = d_dir->d_name;//给p_name赋值遍历文件的文件名,这里右值是结构体对象访问结构体内成员d_name。参照man 3 readdir
    stat(p_name,&st);//使用函数stat绑定文件名和对象st
​
    int n_size,n_link;//定义n_size,n_link,用来存储之后访问到的结果
    n_link = st.st_nlink;//使用stat结构体对象st访问结构体内成员变量st_nlink,并赋值给n_link,stat结构体内st_link用来表示硬链接数
    n_size = st.st_size;//使用stat结构体对象st访问结构体内成员变量st_size,并赋值给n_size,stat结构体内st_size用来表示文件大小
​
#if 1
    char n_dir;//定义一个char变量,用来存放文件类型标识
    if (S_ISREG(st.st_mode))//判断是否为文件类型,S_ISREG详情可以参照man 2 stat
        n_dir = '-';
    else if (S_ISDIR(st.st_mode))//判断是否为目录类型
        n_dir = 'd';
    else if (S_ISCHR(st.st_mode))//判断是否为chr类型
        n_dir = 'c';
    else if (S_ISBLK(st.st_mode))//判断是否为块设备类型
        n_dir = 'b';
    else if (S_ISFIFO(st.st_mode))//判断是否为管道类型
        n_dir = 'p';
    else if (S_ISLNK(st.st_mode))//判断是否为软链接类型
        n_dir = 'l';
    else if (S_ISSOCK(st.st_mode))//判断是否为套接字类型
        n_dir = 's';
    else
        n_dir = '?';//如果都不是,用?表示无法识别
#endif
#if 1
    char n_power[10] = {};//定义一个固定长度的char型数组n_power用来存放九个权限位
    if (S_IRUSR & st.st_mode)//判断用户位是否可读,S_IRUSR详情参照man 2 stat,st_mode位stat结构体中的成员变量
        n_power[0] = 'r';
    else
        n_power[0] = '-';
    if (S_IWUSR & st.st_mode)//判断用户位是否可写
        n_power[1] = 'w';
    else
        n_power[1] = '-';
    if (S_IXUSR & st.st_mode)//判断用户位是否可执行
        n_power[2] = 'x';
    else
        n_power[2] = '-';
    if (S_IRGRP & st.st_mode)//判断用户组位是否可读
        n_power[3] = 'r';
    else
        n_power[3] = '-';
    if (S_IWGRP & st.st_mode)//判断用户组位是否可写
        n_power[4] = 'w';
    else
        n_power[4] = '-';
    if (S_IXGRP & st.st_mode)//判断用户组位是否可执行
        n_power[5] = 'x';
    else
        n_power[5] = '-';
    if (S_IROTH & st.st_mode)//判断其他用户是否可读
        n_power[6] = 'r';
    else
        n_power[6] = '-';
    if (S_IWOTH & st.st_mode)//判断其他用户是否可写
        n_power[7] = 'w';
    else
        n_power[7] = '-';
    if (S_IXOTH & st.st_mode)//判断其他用户是否可执行
        n_power[8] = 'x';
    else
        n_power[8] = '-';
#endif
#if 1
    struct passwd *u_uid = NULL;//定义getpwuid结构体指针u_uid,并初始化为空
    u_uid = getpwuid(st.st_uid);//u_uid指针绑定函数getpwuid(st.st_uid),st_st_uid是stat结构体对象st的成员变量
    if (NULL == u_uid)//判断u_uid指针是否指向成功
    {
        perror("getpwuid");
        exit(0);
    }
    char *g_uid = u_uid->pw_name;//定义char*型指针g_uid用来保存得到的用户名
#endif
​
#if 1
    struct group *gr_gid = NULL;//定义getgrgid结构体指针gr_gid,并初始化为空
    gr_gid = getgrgid(st.st_gid);//gr_gid指针绑定函数getgrgid(st.st_gid),st.st_gid是stat结构体对象st的成员变量
    if (NULL == gr_gid)//判断gr_gid指针是否指向成功
    {
        perror("getgrgid");
        exit(0);
    }
    char *g_gid = gr_gid->gr_name;//定义char*型指针g_gid用来保存得到的组名
#endif
​
#if 1
    struct tm *local_time = NULL;//定义localtime结构体指针local_time,并初始化为空
    local_time = localtime(&st.st_ctime);//local_time指针绑定函数localtime(&st.st_ctime),st.st_ctime是stat结构体对象st的成员变量
​
    if (NULL == local_time) //判断local_time指针是否绑定成功
    {
        perror("localtime");
        exit(0);
    }
    int n_num = local_time->tm_mon;//定义int型变量n_num用来保存local_time指针访问到的月份,注意:这里得到的月份是数字表示,且localtime函数得到的月份是0~11,不符合正常思维的1~12
    char *n_mon;//定义char*型变来嗯n_mon,用来转换数字月份到英文简写月份
    int n_day = local_time->tm_mday;//定义int型变来嗯n_day用来存放local_time指针访问到的日期
    int n_hour = local_time->tm_hour;//定义int型变来嗯n_hour用来存放local_time指针访问到的小时
    int n_min = local_time->tm_min;//定义int型变来嗯n_min用来存放local_time指针访问到的分钟
    switch (n_num)//利用switch-case语句用来转换数字月份到英文简写月份
    {
        case 0:
            n_mon = "Jan";
            break;
        case 1:
            n_mon = "Feb";
            break;
        case 2:
            n_mon = "Mar";
            break;
        case 3:
            n_mon = "Apr";
            break;
        case 4:
            n_mon = "May";
            break;
        case 5:
            n_mon = "Jun";
            break;
        case 6:
            n_mon = "Jul";
            break;
        case 7:
            n_mon = "Aug";
            break;
        case 8:
            n_mon = "Sep";
            break;
        case 9:
            n_mon = "Otc";
            break;
        case 10:
            n_mon = "Nov";
            break;
        case 11:
            n_mon = "Dec";
            break;
        default:
            break;
    }
#endif
    printf("%c%s %d %s %s %d \t %s %d %d:%d\t%s\n",n_dir,n_power,n_link,g_uid,g_gid,n_size,n_mon,n_day,n_hour,n_min,p_name);//输出需要的变量访问结果
    }
    return 0;
}

下面对总体代码进行分步解释。

opendir函数

  • 首先,应该打开目录,这里就使用到了opendir函数,属于c库函数。

  • 打开目录之后,就要读取目录文件中所有文件,即使用readdir函数。readdir函数其实是制定了一个文件指针,指针每跳一次,就读取一个文件名。

  • 这里要注意,每个目录文件中有隐藏文件,ll命令默认是不读取隐藏文件的,所以应该屏蔽之。

  • 文件名的获取是通过readdir函数获取的。

使用opendir函数打开一个目录

[root@localhost c]# man opendir

使用到的头文件:

#include <sys/types.h>
#include <dirent.h>

函数体:

DIR *opendir(const char *name);
函数类型是一个DIR * 类型的指针,传参是一个输入形参数,char*类型

所以定义:

DIR *p_dir = NULL;
        p_dir = opendir(PATH);
        if (NULL == p_dir)  //如果打开失败,则直接退出程序
        {
                perror("opendir");
                exit(0);
        }

readdir函数

readdir函数解析:

[root@localhost day16]# man 3 readdir

用到的头文件:

#include <dirent.h>

函数体:

struct dirent *readdir(DIR *dirp);
//是一个结构体指针,传入参数为DIR*形指针,即目录指针

readdir函数中的结构体:

struct dirent {
               ino_t          d_ino;       /* inode number */
               off_t          d_off;       /* not an offset; see NOTES */
               unsigned short d_reclen;    /* length of this record */
               unsigned char  d_type;      /* type of file; not supported
                                              by all file system types */
               char           d_name[256]; /* filename */
           };
//注意:d_name为filename,即我们需要的文件名

则可以定义:

struct dirent *d_dir = NULL;
//d_dir = readdir(p_dir)就可以将d_dir函数结构体指针与函数绑定,使用while循环,每循环一次,指针跳动一次,即达到遍历目录下所有文件的效果.这里的指针是文件指针。

循环条件:

while (d_dir = readdir(p_dir)){
  ...
}

下来就可以进入到循环体内,进行一系列操作。

过滤掉两个隐藏目录文件

注意:目录内有两个隐藏文件,.和..,如果不需要该文件,应当在循环体内做判断:

f ('.' == *(d_dir->d_name))
                        continue;
//判断是否为隐藏文件,如果是,则跳过

文件名定义

定义一个char*类型的指针,用来存储目录文件下的文件名

char *p_name;

并且将dirent结构体指针指向结构体成员d_name,赋值给p_name。

p_name = d_dir->d_name;

到此,就获取到了目录文件下的文件。

stat函数的结构体

  • 获取到文件名以后,开始获取文件的各个属性,这里用到了stat函数的结构体struct stat。

stat结构体

[root@localhost c]# man 2 stat

用到的头文件:

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

函数体:

int stat(const char *pathname, struct stat *buf);
//返回值为整形,传入参数为输入性参数的文件指针(char*类型),stat结构体指针类型buf

结构体:

struct stat {
               dev_t     st_dev;         /* ID of device containing file */ //文件的设备id
               ino_t     st_ino;         /* inode number */ //文件的inode号
               mode_t    st_mode;        /* file type and mode */   //文件的属性,关于文件类型,文件权限,都依靠该成员
               nlink_t   st_nlink;       /* number of hard links */ //文件硬连接数
               uid_t     st_uid;         /* user ID of owner */     //文件所属用户id
               gid_t     st_gid;         /* group ID of owner */    //文件所属用户组id
               dev_t     st_rdev;        /* device ID (if special file) */  //特殊文件设备id
               off_t     st_size;        /* total size, in bytes */     //文件大小
               blksize_t st_blksize;     /* blocksize for filesystem I/O */ //文件文件系统io的块大小
               blkcnt_t  st_blocks;      /* number of 512B blocks allocated */
​
               /* Since Linux 2.6, the kernel supports nanosecond
                  precision for the following timestamp fields.
                  For the details before Linux 2.6, see NOTES. */
​
               struct timespec st_atim;  /* time of last access */  //访问时间
               struct timespec st_mtim;  /* time of last modification */    //修改内容时间
               struct timespec st_ctim;  /* time of last status change */   //写该属性时间
           #define st_atime st_atim.tv_sec      /* Backward compatibility */
           #define st_mtime st_mtim.tv_sec
           #define st_ctime st_ctim.tv_sec
           };

该结构体里面有各个文件属性,其中有成员st_mode,可以通过该成员计算文件类型和权限值。

定义结构体

struct stat st; //定义一个stat函数的对象st
memset(&st,0,sizeof(st));//清空对象st内存中的垃圾数据
stat(p_name,&st);//使用函数stat绑定文件名和对象st

计算文件大小

struct stat结构体中有st_size成员,用于计算文件大小,返回之值为off_t为整形。则定义:

int n_size;
n_size = st.st_size;
//使用stat结构体对象st访问结构体内成员变量st_size,并赋值给n_size,stat结构体内st_size用来表示文件大小

计算文件硬连接数

struct stat结构体中有st_nlink成员,用于计算文件的硬连接数,返回值为nlink_t为整形。则定义:

int n_link;
n_link=st.st->st_nlink;
//使用stat结构体对象st访问结构体内成员变量st_nlink>,并赋值给n_link,stat结构体内st_link用来表示硬链接数

文件类型

  • linux在一切皆文件的思想下:文件被分为不同类型:目录、普通文件、套接字、字符设备、块设备、管道、链接等。

struct stat结构体中有st_mode,通过一定计算可以从此获取文件类型。有两种风格的判断方式:

system V

在man 2 stat中可以看到该方式的使用方法:

The following mask values are defined for the file type of the  st_mode
       field:
​
           S_IFMT     0170000   bit mask for the file type bit field
​
           S_IFSOCK   0140000   socket
           S_IFLNK    0120000   symbolic link
           S_IFREG    0100000   regular file
           S_IFBLK    0060000   block device
           S_IFDIR    0040000   directory
           S_IFCHR    0020000   character device
           S_IFIFO    0010000   FIFO

即,使用st_mode与不同的类型进行位与计算,如果返回值为1,则说明类型正确,为0则说明错误。

具体使用:

char n_dir; //定义一个char类型变量,用来存放文件类型。
if(S_IFREG & st.st_mode)
                n_dir = '-';

如果判断成功,则将"-"字符赋值给n_dir。

POSIX

第二种风格是posix风格的方式:使用man 2 stat可以查看:

Because  tests  of  the  above  form  are common, additional macros are
       defined by POSIX to allow the test of the file type in  st_mode  to  be
       written more concisely:
​
           S_ISREG(m)  is it a regular file?
​
           S_ISDIR(m)  directory?
​
           S_ISCHR(m)  character device?
​
           S_ISBLK(m)  block device?
​
           S_ISFIFO(m) FIFO (named pipe)?
​
           S_ISLNK(m)  symbolic link?  (Not in POSIX.1-1996.)
​
           S_ISSOCK(m) socket?  (Not in POSIX.1-1996.)

即:将st_mode作为参数,传给不同类型的mode,进行判断,如果返回1,则表示类型匹配,返回0,则表示类型不匹配。具体:

char n_dir;
if (S_ISDIR(st.st_mode))//判断是否为目录类型
                n_dir = 'd';

如果判断成功,则将"d"字符赋值给n_dir。

这里使用了POSIX风格进行计算文件类型

具体代码:

#if 1
        char n_dir;//定义一个char变量,用来存放文件类型标识
        if (S_ISREG(st.st_mode))//判断是否为文件类型,S_ISREG详情可以参照man 2 stat
                n_dir = '-';
        else if (S_ISDIR(st.st_mode))//判断是否为目录类型
                n_dir = 'd';
        else if (S_ISCHR(st.st_mode))//判断是否为chr类型
                n_dir = 'c';
        else if (S_ISBLK(st.st_mode))//判断是否为块设备类型
                n_dir = 'b';
        else if (S_ISFIFO(st.st_mode))//判断是否为管道类型
                n_dir = 'p';
        else if (S_ISLNK(st.st_mode))//判断是否为软链接类型
                n_dir = 'l';
        else if (S_ISSOCK(st.st_mode))//判断是否为套接字类型
                n_dir = 's';
        else
                n_dir = '?';//如果都不是,用?表示无法识别
#endif

文件权限

  • 通过ll命令,我们知道文件权限除了文件类型还有9个字符,则可以定一个10位的char型数组来存放。

定义方法:

 char n_power[10] = {};//定义一个固定长度的char型数组n_power用来存放九个权限位

具体获取每位的权限,还是要使用stat结构体中st_mode成员。具体方法,man 2 stat:

The  following  mask values are defined for the file mode component of the st_mode
       field:
​
           S_ISUID     04000   set-user-ID bit
           S_ISGID     02000   set-group-ID bit (see below)
           S_ISVTX     01000   sticky bit (see below)
​
           S_IRWXU     00700   owner has read, write, and execute permission
           S_IRUSR     00400   owner has read permission
           S_IWUSR     00200   owner has write permission
           S_IXUSR     00100   owner has execute permission
           S_IXUSR     00100   owner has execute permission
​
           S_IRWXG     00070   group has read, write, and execute permission
           S_IRGRP     00040   group has read permission
           S_IWGRP     00020   group has write permission
           S_IXGRP     00010   group has execute permission
​
           S_IRWXO     00007   others (not in group) have read,  write,  and
                               execute permission
           S_IROTH     00004   others have read permission
           S_IWOTH     00002   others have write permission
           S_IXOTH     00001   others have execute permission

可以看到里面有:S_IRUSR、S_IWUSR、S_IXUSR、S_IRGRPS_IWGRP、S_IXGRP、S_IROTH、S_IWOTH、S_IXOTH九个值,分别代表权限上的九位。计算方法,将这九个值分别和st_mode进行位与计算,返回值为1,则表示该权限存在,返回值为0,则表示该权限不存在。

具体:

char n_power[10] = {};//定义一个固定长度的char型数组n_power用来存放九个权限位
        if (S_IRUSR & st.st_mode)//判断用户位是否可读,S_IRUSR详情参照man 2 stat,st_mode位stat结构体中的成员变量
                n_power[0] = 'r';
        else
                n_power[0] = '-';
        if (S_IWUSR & st.st_mode)//判断用户位是否可写
                n_power[1] = 'w';
        else
                n_power[1] = '-';
        if (S_IXUSR & st.st_mode)//判断用户位是否可执行
                n_power[2] = 'x';
        else
                n_power[2] = '-';
        if (S_IRGRP & st.st_mode)//判断用户组位是否可读
                n_power[3] = 'r';
        else
                n_power[3] = '-';
        if (S_IWGRP & st.st_mode)//判断用户组位是否可写
                n_power[4] = 'w';
        else
                n_power[4] = '-';
        if (S_IXGRP & st.st_mode)//判断用户组位是否可执行
                n_power[5] = 'x';
        else
                n_power[5] = '-';
        if (S_IROTH & st.st_mode)//判断其他用户是否可读
                n_power[6] = 'r';
        else
                n_power[6] = '-';
        if (S_IWOTH & st.st_mode)//判断其他用户是否可写
                n_power[7] = 'w';
        else
                n_power[7] = '-';
        if (S_IXOTH & st.st_mode)//判断其他用户是否可执行
                n_power[8] = 'x';
        else
                n_power[8] = '-';

文件所属用户

以为stat中的结构体只能获取到所属用户的id号,而不能获取所属用户用户名,所以这里还要使用getpwuid函数。具体:

[root@localhost day16]# man getpwuid

使用到的头文件:

#include <sys/types.h>
#include <pwd.h>

函数体:

struct passwd *getpwuid(uid_t uid);
//返回值类型是一个结构体指针类型,传入参数为uid_t类型的uid值

结构体:

The passwd structure is defined in <pwd.h> as follows:
​
           struct passwd {
               char   *pw_name;       /* username */
               char   *pw_passwd;     /* user password */
               uid_t   pw_uid;        /* user ID */
               gid_t   pw_gid;        /* group ID */
               char   *pw_gecos;      /* user information */
               char   *pw_dir;        /* home directory */
               char   *pw_shell;      /* shell program */
           };
//注意里面pw_name为我们需要的用名

则,先定义一个passwd结构体:

struct passwd *u_uid = NULL;//定义getpwuid结构体指针u_uid,并初始化为空

然后将stat结构体中的st.st_uid作为参数传给getpwuid。并将结果赋值给u_uid。

u_uid = getpwuid(st.st_uid);//u_uid指针绑定函数getpwuid(st.st_uid),st_st_uid是stat>结构体对象st的成员变量

这里最好判断一下是否赋值成功

if (NULL == u_uid)//判断u_uid指针是否指向成功
        {
                perror("getpwuid");
                exit(0);
        }

然后定一个char*类型的指针,保存得到的用户名:

char *g_uid = u_uid->pw_name;//定义char*型指针g_uid用来保存得到的用户名

文件所属用户组

以为stat中的结构体只能获取到所属用户组的id号,而不能获取所属用户用户组的组名,所以这里还要使用gegrgid函数。具体:

[root@localhost day16]# man getgrgid

使用到的头文件:

 #include <sys/types.h>
 #include <grp.h>

函数体:

struct group *getgrgid(gid_t gid);
//返回值类型为结构体指针类型,传入参数为gid_t类型的gid(所数组的组id)

结构体:

struct group {
               char   *gr_name;       /* group name */
               char   *gr_passwd;     /* group password */
               gid_t   gr_gid;        /* group ID */
               char  **gr_mem;        /* group members */
           };
//注意:gr_name为我们需要计算的文件所属用户组组名

具体:

先定义一个group结构体指针:

struct group *gr_gid = NULL;//定义getgrgid结构体指针gr_gid,并初始化为空

然后,将stat函数结构体中获取的st_gid作为参数,传入getgrgid函数,将结果赋值给gr_gid(group结构体指针类型变量)。

gr_gid = getgrgid(st.st_gid);//gr_gid指针绑定函数getgrgid(st.st_gid),st.st_gid是stat结构体对象st的成员变量

最好做一下判断

if (NULL == gr_gid)//判断gr_gid指针是否指向成功
        {
                perror("getgrgid");
                exit(0);
        }

定义一个char*类型变量用来保存获取到的用户组名称:

char *g_gid = gr_gid->gr_name;//定义char*型指针g_gid用来保存得到的组名

获取时间

获取时间使用了localtime函数,查看一下localtime相关参数:

[root@localhost day16]# man localtime

使用到的头文件:

 #include <time.h>

函数体:

struct tm *localtime(const time_t *timep);
//函数返回值为结构体指针,传入参数为一个输入形指针参数

从stat结构体的成员变量mtime中获取到localtime的参数,并定义一个struct tm *的指针保存函数返回值。

tm结构体:

struct tm {
               int tm_sec;         /* seconds */
               int tm_min;         /* minutes */
               int tm_hour;        /* hours */
               int tm_mday;        /* day of the month */
               int tm_mon;         /* month */
               int tm_year;        /* year */
               int tm_wday;        /* day of the week */
               int tm_yday;        /* day in the year */
               int tm_isdst;       /* daylight saving time */
           };
//从ll命令可以看出来我们需要获取,tm_mon、tm_day、tm_hour、tm_min

则,具体:

struct tm *local_time = NULL;//定义localtime结构体指针local_time,并初始化为空
        local_time = localtime(&st.st_mtime);//local_time指针绑定函数localtime(&st.st_mtime),st.st_mtime是stat结构体对象st的成员变量
​
        if (NULL == local_time) //判断local_time指针是否绑定成功
        {
                perror("localtime");
                exit(0);
        }
        int n_num = local_time->tm_mon;//定义int型变量n_num用来保存local_time指针访问到的月>份,注意:这里得到的月份是数字表示,且localtime函数得到的月份是0~11,不符合正常思维的1~12
        char *n_mon;//定义char*型变来嗯n_mon,用来转换数字月份到英文简写月份
        int n_day = local_time->tm_mday;//定义int型变来嗯n_day用来存放local_time指针访问到的
日期
        int n_hour = local_time->tm_hour;//定义int型变来嗯n_hour用来存放local_time指针访问到
的小时
        int n_min = local_time->tm_min;//定义int型变来嗯n_min用来存放local_time指针访问到的>分钟

这里,tm_mon的返回值为0-11,ll命令显示的是各个月份的英文字母缩写,所以需要进行转换:

switch (n_num)//利用switch-case语句用来转换数字月份到英文简写月份
        {
                case 0:
                        n_mon = "Jan";
                        break;
                case 1:
                        n_mon = "Feb";
                        break;
                case 2:
                        n_mon = "Mar";
                        break;
                case 3:
                        n_mon = "Apr";
                        break;
                case 4:
                        n_mon = "May";
                        break;
                case 5:
                        n_mon = "Jun";
                        break;
                case 6:
                        n_mon = "Jul";
                        break;
                case 7:
                        n_mon = "Aug";
                        break;
                case 8:
                        n_mon = "Sep";
                        break;
                case 9:
                        n_mon = "Otc";
                        break;
                case 10:
                        n_mon = "Nov";
                        break;
                case 11:
                        n_mon = "Dec";
                        break;
                default:
                        break;
        }

输出函数

搞定以后,进行排序输出:

printf("%c%s %d %s %s %d \t %s %d %d:%d\t%s\n",n_dir,n_power,n_link,g_uid,g_gid,n_size,n_mon,n_day,n_hour,n_min,p_name);//输出需要的变量访问结果

测试结果:

[root@localhost day16]# gcc ls_res.c -o my_ls
[root@localhost day16]# ./my_ls 
drwxrwxrwx 3 root root 4096      May 5 11:38    fsx_test_1
drwxrwxrwx 3 root root 4096      May 5 11:38    after
drwxrwxrwx 3 root root 4096      May 5 11:38    fsx_test_2
-rwxr-xr-x 1 root root 13072     Aug 16 21:0    a.out
-rwxrwxrwx 1 root root 6126      Aug 16 21:2    ls_res.c
drwxrwxrwx 2 root root 4096      May 5 11:38    mor
-rwxr-xr-x 1 root root 13072     Aug 16 21:4    my_ls
drwxrwxrwx 3 root root 4096      May 5 11:38    teacher
-rw-r--r-- 1 root root 23586     Aug 16 21:2    stat.txt
-rw-r--r-- 1 root root 0     Aug 16 20:50   fsx

对比ll命令:

[root@localhost day16]# ll
total 84
drwxrwxrwx. 3 root root  4096 May  5 11:38 after
-rwxr-xr-x  1 root root 13072 Aug 16 21:00 a.out
-rw-r--r--  1 root root     0 Aug 16 20:50 fsx
drwxrwxrwx. 3 root root  4096 May  5 11:38 fsx_test_1
drwxrwxrwx. 3 root root  4096 May  5 11:38 fsx_test_2
-rwxrwxrwx. 1 root root  6126 Aug 16 21:02 ls_res.c
drwxrwxrwx. 2 root root  4096 May  5 11:38 mor
-rwxr-xr-x  1 root root 13072 Aug 16 21:04 my_ls
-rw-r--r--  1 root root 23586 Aug 16 21:02 stat.txt
drwxrwxrwx. 3 root root  4096 May  5 11:38 teacher

还是有些不完美哈。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值