Linux Ubuntu下的目录操作实现ls -l功能(C语言)

发布于:2022-08-06 ⋅ 阅读:(556) ⋅ 点赞:(0)

       大家好,我是练习编程时长两年半的个人练习生昆工第一ikun,今天我们来分享一下目录文件的操作,并实现“ls -l”功能的实现,话不多说,上代码!!


目录

一、目录操作

1、打开目录 -- opendir

2、读取目录 -- readdir

3、关闭目录 -- closedir

4、获取文件属性 -- lstat

二、实现ls -l命令功能


一、目录操作

1、打开目录 -- opendir

   #include <sys/types.h>
   #include <dirent.h>
​
   DIR *opendir(const char *name);
   参数:
    name:要打开的目录名
   返回值:
    成功返回目录流指针,返回NULL;

2、读取目录 -- readdir

readdir一次只能随机读取一个目录项

   #include <dirent.h>
​
   struct dirent *readdir(DIR *dirp);
   
          struct dirent {
               char           d_name[256]; /*文件名*/
           };

3、关闭目录 -- closedir

   #include <sys/types.h>
​
   #include <dirent.h>
​
   int closedir(DIR *dirp);
   
   参数:
    dirp:目录流指针
   返回值:
    成功返回0,失败返回-1

4、获取文件属性 -- lstat

   #include <sys/types.h>
   #include <sys/stat.h>
   #include <unistd.h>
​
   int stat(const char *pathname, struct stat *statbuf);
   int fstat(int fd, struct stat *statbuf);
   int lstat(const char *pathname, struct stat *statbuf);
   参数:
    pathname:文件名
    statbuf:存放文件信息的结构体地址
   返回值:
    成功返回0,失败返回-1;
    
    struct stat
    {
               mode_t    st_mode;        //文件类型和权限
               nlink_t   st_nlink;       //文件硬链接数
               uid_t     st_uid;         //用户ID
               gid_t     st_gid;         //用户组ID
               off_t     st_size;        //文件大小
               struct timespec st_mtim;  //最后修改文件时间
​
               #define st_mtime st_mtim.tv_sec
    }
    
    getgrgid -- 得到用户组名的函数
    getpwuid -- 得到用户名的函数

获取文件类型: 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 & S_IFMT等于对应文件类型宏,则文件类型宏对应类型就为文件类型
    
    获取文件权限:
            st_mode & 对应权限宏 == 宏本身 表示具有该权限
​
           S_IRUSR     00400   owner has read permission
           S_IWUSR     00200   owner has write permission
           S_IXUSR     00100   owner has execute permission
​
           S_IRGRP     00040   group has read permission
           S_IWGRP     00020   group has write permission
           S_IXGRP     00010   group has execute permission
    
           S_IROTH     00004   others have read permission
           S_IWOTH     00002   others have write permission
           S_IXOTH     00001   others have execute permission

 

二、实现ls -l命令功能

       我们都知道Linux Ubuntu下有一个命令“ls -l”可以查看文件的类型、权限、硬链接数、用户名、用户组名、大小、更新时间、文件名。如下图:

       那么我们能不能自己编写一个程序来实现这个功能呢,那就要用到今天分享的目录操作,我们来看代码。

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

int main(int argc, char *argv[])
{
    DIR *dir = opendir(".");
    if(dir == NULL)
    {
        perror("opendir");
        return -1;
    }
    struct dirent *read = NULL;
    struct stat s;
    struct tm *t = NULL;
    struct passwd *uid = NULL;
    struct group *gid = NULL;
    char str[4] = {'x','w', 'r', '-'};
    while((read = readdir(dir)) != NULL)
    {
        if(read->d_name[0] != '.')
        {
            lstat(read->d_name, &s);
            switch(s.st_mode & S_IFMT)
            {
                case S_IFSOCK:
                    printf("s");
                    break;
                case S_IFLNK:
                    printf("l");
                    break;
                case S_IFREG:
                    printf("-");
                    break;
                case S_IFBLK:
                    printf("b");
                    break;
                case S_IFDIR:
                    printf("d");
                    break;
                case S_IFCHR:
                    printf("c");
                    break;
                case S_IFIFO:
                    printf("p");
                    break;
            }

            for(int i = 8; i >= 0; i--)
            {
                if(s.st_mode & 1 << i)
                {
                    printf("%c", str[i%3]);
                }
                else
                {
                    printf("%c", str[3]);
                }
            }
            printf("%4ld  ", s.st_nlink);
            uid = getpwuid(s.st_uid);
            printf("%2s  ", uid->pw_name);
            gid = getgrgid(s.st_gid);
            printf("%2s  ", gid->gr_name);
            printf("%-8ld  ", s.st_size);
            t = localtime(&s.st_mtime);
            printf("%d月  %2d %2d:%d  ", t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min);
            printf("%-8s  ", read->d_name);
            printf("\n");

        }
    }
    closedir(dir);

    return 0;
} 

运行代码,我们可以实现和“ls -l”命令一样的功能,如下图:

 

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到