【无标题】

这篇博客介绍了如何使用C语言的系统调用来实现类似`ls -l`命令的功能,包括打开和关闭目录、读取目录内容、获取文件属性等。通过示例代码展示了如何解析文件类型和权限,并输出文件的详细信息,如所有者、用户组、大小和修改时间。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

注:不管用什么调用函数,都记得加上查看man手册时的头文件

1、打开、关闭目录–opendir/closedir

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

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

int closedir(DIR *dirp);
参数:dirp:目录流指针
    返回值:
		成功返回目录名,失败返回NULL;

2、读取目录–readdir

#include <dirent.h>

struct dirent *readdir(DIR *dirp);

struct dirent {
    char    d_name[256]; /* Null-terminated filename */
};

3、获取文件属性–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);
参数:
返回值:
    成功返回0,失败返回-1
    
struct stat {
    dev_t     st_dev;         /* ID of device containing file */
    ino_t     st_ino;         /* Inode number */
    mode_t    st_mode;        /* File type and mode */
    nlink_t   st_nlink;       /* Number of hard links */
    uid_t     st_uid;         /* User ID of owner */
    gid_t     st_gid;         /* Group ID of owner */
    dev_t     st_rdev;        /* Device ID (if special file) */
    off_t     st_size;        /* Total size, in bytes */
    blksize_t st_blksize;     /* Block size for filesystem I/O */
    blkcnt_t  st_blocks;      /* Number of 512B blocks allocated */
}
    
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
    

4、练习—接下来我们用一个实例来练习对目录的操作:

	对目录进行操作获取ls信息:就是用目录调用函数来实现ls -l的效果
	这是ls的终端显示:

在这里插入图片描述

我们来看看函数的实现,基本上用到了我们所有目录函数的调用:


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


int main(int argc, char *argv[])
{ 
    DIR *opd=opendir(".");//打开当前目录,'.'也可以换成其他路径的目录
    //定义需要用到的结构体,具体可以查看man手册
    struct dirent *buf=NULL;
    struct stat arr;
    struct tm *t;
    struct group *gp;
    struct passwd *pd;
    int ret,ret1;
    char typef[10]={0};//定义判断文件类型及其权限的缓冲区
    if(NULL==opd)
    {
        perror("opendir");
        return -1;
    }
    while((buf=readdir(opd))!=NULL)//读取目录,为空才结束
    {
        if(buf->d_name[0]!='.')//不显示隐藏文件
        {
            lstat(buf->d_name,&arr);//获取文件名
            if(ret1<0)
            {
                perror("lstat");
                return -1;
            }
            switch(arr.st_mode & S_IFMT)//st_mode & 对应权限宏 ==宏本身 表示具有该权限
            {
                case S_IFREG:typef[0]='-';//普通文件
                             break;
                case S_IFLNK:typef[0]='l';//链接文件
                             break;
                case S_IFDIR:typef[0]='d';//目录文件
                             break;
                case S_IFBLK:typef[0]='b';//块设备文件
                             break;
                case S_IFIFO:typef[0]='p';//管道文件
                             break;
                case S_IFCHR:typef[0]='c';//字符设备文件
                             break;
                case S_IFSOCK:typef[0]='s';//套接字文件
                             break;
                default:break;
            }
            //用户(ower)权限
            typef[1]=(arr.st_mode & S_IRUSR)?'r':'-';
            typef[2]=(arr.st_mode & S_IWUSR)?'w':'-';
            typef[3]=(arr.st_mode & S_IXUSR)?'x':'-';
            //组(group)权限
            typef[4]=(arr.st_mode & S_IRUSR)?'r':'-';
            typef[5]=(arr.st_mode & S_IWUSR)?'w':'-';
            typef[6]=(arr.st_mode & S_IXUSR)?'x':'-';
            //其他(other)权限
            typef[7]=(arr.st_mode & S_IRUSR)?'r':'-';
            typef[8]=(arr.st_mode & S_IWUSR)?'w':'-';
            typef[9]=(arr.st_mode & S_IXUSR)?'x':'-';
            
            printf("%-14s ",buf->d_name);
            printf("%s",typef);
            printf(" ");
            printf("%ld ",arr.st_nlink);//链接文件数

            pd=getpwuid(arr.st_uid);//用户名
            gp=getgrgid(arr.st_gid);//用户组名
            printf("%s ",gp->gr_name);
            printf("%s ",pd->pw_name);

            printf("%-8ld",arr.st_size);//文件大小
            t=localtime(&arr.st_mtime);//获取时间
            printf("%d月 %d %d:%d\n",t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min);//定义自己想要的时间格式
        }
    }
    puts("");
    ret=closedir(opd);//关闭目录
    if(ret<0)
    {
        perror("closedir");
        return -1;
    }
    return 0;
} 

看看代码终端的显示效果:
在这里插入图片描述
这样就能实现ls -l的效果了,甚至还能根据自己的喜好需求,增加、删除其他的内容,调正输出的一些格式尺寸。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值