Linux(四)函数获知文件、目录的属性、权限

9 篇文章 0 订阅
7 篇文章 0 订阅

Linux(四)函数获知文件、目录的属性、权限

ubuntu下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xLQB8zVb-1641384335348)(C:\Users\纵横四海\AppData\Roaming\Typora\typora-user-images\image-20211212180944079.png)]

用函数判断文件的权限、类型,需要用到上图所示的宏常量,这些宏定义在C语言库里,我们可以直接使用这些宏。

一、获取文件属性

1.1 stat

函数功能:通过文件名(带路径)获取文件属性(节点号、文件类型、链接数、属主 ID、文件大小等 )

函数原型:int stat(const char *path,struct stat *buf)

头文件:#include<sys/types.h>、#include<sys/stat.h>、#include<unistd.h>

参数:const char *path: 带路径的文件名,

​ struct stat *buf :文件属性结构体变量的地址

			struct stat {
							dev_t st_dev; /*如果是设备,返回设备表述符,否则为 0*/
							ino_t st_ino; /* i 节点号 */
							mode_t
							mode st_mode; /* 文件类型 */
							nlink_t st_nlink; /* 链接数 */
							uid_t st_uid; /* 属主 ID */
							gid_t st_gid; /* 组 ID */
							dev_t st_rdev; /* 设备类型*/
							off_t st_size; /* 文件大小,字节表示 */
							blksize_t st_blksize; /* 系统每次按块Io操作时块的大小(一般是512或1024)*/
							blkcnt_t st_blocks; /*块的索引号 */
							time_t st_atime; /* 最后访问时间,如read*/
							time_t st_mtime; /* 最后修改时间*/
							time_t st_ctime; /*显示的是文件的权限、拥有者、所属的组、链接数发生改变时的时间。当然当内容改变时也会随之改变 */
					};

返回值:成功返回0,失败返回-1

示例代码:通过stat函数 获取文件 属性 模仿ls -ail 的功能

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


struct stat buf;

int main(int argv,char* argc[])
{
    char fileProperty[11]={'-','-','-','-','-','-','-','-','-','-','\0'}; //存储文件类型(第1个字节)和读写权限(后9个字节)
    unsigned long nlink; //链接数

    stat(argc[1],&buf);

    /*获取文件的类型*/
    switch ((buf.st_mode&S_IFMT))
    {
        case S_IFSOCK: fileProperty[0] = 's'; break;//套节字文件(s)
        case S_IFREG: fileProperty[0] = '-'; break;//普通文件(-)
        case S_IFLNK: fileProperty[0] = 'l'; break;//链接文件(l)
        case S_IFCHR: fileProperty[0] = 'c'; break;//字符设备文件(c)
        case S_IFIFO: fileProperty[0] = 'p'; break;//管道文件(p)
        case S_IFDIR: fileProperty[0] = 'd'; break;//目录文件(d)
        case S_IFBLK: fileProperty[0] = 'b'; break;//块设备文件(b)
        default:
            break;
    }

    /*获取文件的读写权限*/
    char i = 1;
    unsigned int off = 256; 
    
    for (char j = 0; j < 10; j++)
    {
        switch (buf.st_mode&off>>j)
        {
            case S_IRUSR: fileProperty[1] = 'r'; break;//文件所属用户
            case S_IWUSR: fileProperty[2] = 'w'; break;//文件所属用户
            case S_IXUSR: fileProperty[3] = 'x'; break;//文件所属用户
            case S_IRGRP: fileProperty[4] = 'r'; break;//组用户
            case S_IWGRP: fileProperty[5] = 'w'; break;//组用户
            case S_IXGRP: fileProperty[4] = 'x'; break;//组用户
            case S_IROTH: fileProperty[7] = 'r'; break;//其他用户
            case S_IWOTH: fileProperty[8] = 'w'; break;//其他用户
            case S_IXOTH: fileProperty[9] = 'x'; break;//其他用户             
            default:
                break;
        }
    }

    /*获取链接数*/
    nlink = buf.st_nlink;

    /*通过文件所属的用户ID,获取文件所属用户名*/
    //获取到 user_id, group_id, 调用 getpwuid/getgrgid 即可
    struct passwd * user = NULL;
    struct group * group = NULL;  
    
    user = getpwuid(buf.st_uid);
    group = getgrgid(buf.st_gid);

    /*获取文件大小*/
    unsigned long fileSize;
    fileSize = buf.st_size;

    /*获取最近修改时间*/
    struct tm *loTim = NULL;
    loTim = localtime(&buf.st_ctime);
    
    /*******输出文件属性信息********/

    printf("%lu  %s %lu %s %s  %lu  %d年%02d月%02d日 %02d:%02d:%02d %s\n",buf.st_ino,fileProperty,nlink,user->pw_name,group->gr_name,fileSize,loTim->tm_year + 1900,loTim->tm_mon+1,loTim->tm_mday,loTim->tm_hour,loTim->tm_min,loTim->tm_sec,argc[1]);

    return 0;
}
1.2 fstat

函数功能:通过文件描述符获取文件属性(节点号、文件类型、链接数、属主 ID、文件大小等 ),需要打开文件获取文件描述符,用法与stat类似

函数原型:int fstat(int fds,struct stat *buf);

头文件:#include<sys/types.h>、#include<sys/stat.h>、#include<unistd.h>

参数:int fds : 文件描述符

​ struct stat *buf : 文件属性结构体变量的地址

返回值:成功返回0,失败返回-1

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

struct stat buf;

int main(int argv,char* argc[])
{
    char fileProperty[11]={'-','-','-','-','-','-','-','-','-','-','\0'}; //存储文件类型(第1个字节)和读写权限(后9个字节)
    unsigned long nlink; //链接数
    int fd;
    fd = open(argc[1],O_RDONLY);
    // stat(argc[1],&buf);
    fstat(fd,&buf);

    /*获取文件的类型*/
    switch ((buf.st_mode&S_IFMT))
    {
        case S_IFSOCK: fileProperty[0] = 's'; break;//套节字文件(s)
        case S_IFREG: fileProperty[0] = '-'; break;//普通文件(-)
        case S_IFLNK: fileProperty[0] = 'l'; break;//链接文件(l)
        case S_IFCHR: fileProperty[0] = 'c'; break;//字符设备文件(c)
        case S_IFIFO: fileProperty[0] = 'p'; break;//管道文件(p)
        case S_IFDIR: fileProperty[0] = 'd'; break;//目录文件(d)
        case S_IFBLK: fileProperty[0] = 'b'; break;//块设备文件(b)
        default:
            break;
    }

    /*获取文件的读写权限*/
    char i = 1;
    unsigned int off = 256;
    
    for (char j = 0; j < 10; j++)
    {
        switch (buf.st_mode&off>>j)
        {
            case S_IRUSR: fileProperty[1] = 'r'; break;
            case S_IWUSR: fileProperty[2] = 'w'; break;
            case S_IXUSR: fileProperty[3] = 'x'; break;
            case S_IRGRP: fileProperty[4] = 'r'; break;
            case S_IWGRP: fileProperty[5] = 'w'; break;
            case S_IXGRP: fileProperty[4] = 'x'; break;
            case S_IROTH: fileProperty[7] = 'r'; break;
            case S_IWOTH: fileProperty[8] = 'w'; break;
            case S_IXOTH: fileProperty[9] = 'x'; break;             
            default:
                break;
        }
    }


    /*获取链接数*/
    nlink = buf.st_nlink;

    /*通过文件所属的用户ID,获取文件所属用户名*/
    //获取到 user_id, group_id, 调用 getpwuid/getgrgid 即可
    struct passwd * user = NULL;
    struct group * group = NULL;  

    user = getpwuid(buf.st_uid);
    group = getgrgid(buf.st_gid);


    /*获取文件大小*/
    unsigned long fileSize;
    fileSize = buf.st_size;

    /*获取最近修改时间*/
    // char* localTime = ctime(buf.st_ctime);
    
    /*******输出文件属性信息********/
    struct tm *loTim = NULL;
    loTim = localtime(&buf.st_ctime);

    printf("%lu  %s %lu %s %s  %lu  %d年%02d月%02d日 %02d:%02d:%02d %s\n",buf.st_ino,fileProperty,nlink,user->pw_name,group->gr_name,fileSize,loTim->tm_year + 1900,loTim->tm_mon+1,loTim->tm_mday,loTim->tm_hour,loTim->tm_min,loTim->tm_sec,argc[1]);

    return 0;
}
1.3 lstat

函数功能:获取的是链接文件的文件属性(节点号、文件类型、链接数、属主 ID、文件大小等 ),需要打开文件获取文件描述符,用法与stat类似

函数原型:int lstat(const char *path,struct stat *buf);

头文件:#include<sys/types.h>、#include<sys/stat.h>、#include<unistd.h>

参数:const char *path : 文件名(含路径)

​ struct stat *buf : 文件属性结构体变量的地址

返回值:成功返回0,失败返回-1

示例:

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


struct stat buf;

int main(int argv,char* argc[])
{
    char fileProperty[11]={'-','-','-','-','-','-','-','-','-','-','\0'}; //存储文件类型(第1个字节)和读写权限(后9个字节)
    unsigned long nlink; //链接数
    int fd;
    // fd = open(argc[1],O_RDONLY);
    // stat(argc[1],&buf);
    // fstat(fd,&buf);

    lstat(argc[1],&buf);

    /*获取文件的类型*/
    switch ((buf.st_mode&S_IFMT))
    {
        case S_IFSOCK: fileProperty[0] = 's'; break;//套节字文件(s)
        case S_IFREG: fileProperty[0] = '-'; break;//普通文件(-)
        case S_IFLNK: fileProperty[0] = 'l'; break;//链接文件(l)
        case S_IFCHR: fileProperty[0] = 'c'; break;//字符设备文件(c)
        case S_IFIFO: fileProperty[0] = 'p'; break;//管道文件(p)
        case S_IFDIR: fileProperty[0] = 'd'; break;//目录文件(d)
        case S_IFBLK: fileProperty[0] = 'b'; break;//块设备文件(b)
        default:
            break;
    }

    /*获取文件的读写权限*/
    char i = 1;
    unsigned int off = 256;
    
    for (char j = 0; j < 10; j++)
    {
        switch (buf.st_mode&off>>j)
        {
            case S_IRUSR: fileProperty[1] = 'r'; break;
            case S_IWUSR: fileProperty[2] = 'w'; break;
            case S_IXUSR: fileProperty[3] = 'x'; break;
            case S_IRGRP: fileProperty[4] = 'r'; break;
            case S_IWGRP: fileProperty[5] = 'w'; break;
            case S_IXGRP: fileProperty[4] = 'x'; break;
            case S_IROTH: fileProperty[7] = 'r'; break;
            case S_IWOTH: fileProperty[8] = 'w'; break;
            case S_IXOTH: fileProperty[9] = 'x'; break;             
            default:
                break;
        }
    }


    /*获取链接数*/
    nlink = buf.st_nlink;

    /*通过文件所属的用户ID,获取文件所属用户名*/
    //获取到 user_id, group_id, 调用 getpwuid/getgrgid 即可
    struct passwd * user = NULL;
    struct group * group = NULL;  

    user = getpwuid(buf.st_uid);
    group = getgrgid(buf.st_gid);


    /*获取文件大小*/
    unsigned long fileSize;
    fileSize = buf.st_size;

    /*获取最近修改时间*/
    // char* localTime = ctime(buf.st_ctime);
    
    /*******输出文件属性信息********/
    struct tm *loTim = NULL;
    loTim = localtime(&buf.st_ctime);

    printf("%lu  %s %lu %s %s  %lu  %d年%02d月%02d日 %02d:%02d:%02d %s\n",buf.st_ino,fileProperty,nlink,user->pw_name,group->gr_name,fileSize,loTim->tm_year + 1900,loTim->tm_mon+1,loTim->tm_mday,loTim->tm_hour,loTim->tm_min,loTim->tm_sec,argc[1]);

    return 0;
}

结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7cX3l4ve-1641384335350)(C:\Users\纵横四海\AppData\Roaming\Typora\typora-user-images\image-20220102223203662.png)]

  • stat 和 fstat的差别:stat通过文件名获取文件属性(不需要打开文件),fstat通过文件描述符获取属性(需要打开文件)
  • stat 和 lstat的区别:stat获取文件的属性的时候获取的是链接文件所指向的文件的属性,lstat获取的是链接文件的属性
通过shell指令获取文件属性
ls -ail
ls 命令实际上就是调用stat等系统调用的函数读取文件属性并显示出来
1.4 access

函数功能:检测当前用户(运行这个程序的用户)对该文件是否有某权限

函数原型:int access(const char *pathname, int mode);

头文件:#include<unistd.h>

参数:const char *pathname : 文件名(含路径)

​ int mode:权限类型,可组合使用

​ R_OK:测试读权限

					W_OK:测试写权限

					X_OK:测试执行权限

​ F_OK:测试文件是否存在 : 文件属性结构体变量的地址

返回值:成功返回0,失败返回-1

示例:

#include<stdio.h>
#include <unistd.h>


int main(int argv,char* argc[])
{
    int status;
    status = access(argc[1],R_OK);
    if (status < 0)
    {
        printf("无读权限\n");
    }
    else
    {
        printf("有读权限\n");
    }
    return 0;
}

结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ba6Dd5uJ-1641384335352)(C:\Users\纵横四海\AppData\Roaming\Typora\typora-user-images\image-20220103001827134.png)]

二、目录操作

2.1 mkdir

函数功能:创建目录文件(不能一次创建多级目录)

函数原型:int mkdir(const char *pathname, mode_t mode);

头文件:#include<sys/types.h>、#include<sys/stat.h>

参数:const char *pathname: 文件名(含路径)

​ mode: 文件权限用数字或宏表示

返回值:成功返回0,失败返回-1

示例:

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

#define U8 unsigned char

int main(void)
{
    U8 status;

    status = mkdir("dir1",0664);

    if (status < 0)
    {
        perror("mkdir");
    }

    printf("操作结束\n");

    return 0;
}

结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S7med1bx-1641384335353)(C:\Users\纵横四海\AppData\Roaming\Typora\typora-user-images\image-20220103194829269.png)]

2.2 rmdir

函数功能:删除目录文件(只能删除空文件)

函数原型:int rmdir(const char *pathname);

头文件:#include<sys/types.h>、#include<sys/stat.h>

参数:const char *pathname: 要删除的目录路径

返回值:成功返回0,失败返回-1

#include<stdio.h>
#include<unistd.h>
#define U8 unsigned char

int main(void)
{
    U8 status;
    status = rmdir("dir1");

    if (status < 0)
    {
        perror("rmdir");
    }

    printf("操作结束\n");
    return 0;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5wk0L6de-1641384335354)(C:\Users\纵横四海\AppData\Roaming\Typora\typora-user-images\image-20220103195758140.png)]

2.3 getcwd(类似于shell指令里的pwd)

函数功能:获取当前所在路径

函数原型:char *getcwd(char *buf, size_t size);

头文件:#include<unistd.h>

参数: buf:存放路径的缓存区

		 size:缓存区的大小 能保存的最大值为255 路径长度最多能是255

返回值:成功返回路径,失败返回NULL

示例:

#include<stdio.h>
#include<unistd.h>

#define U8 unsigned char

int main(void)
{
    U8 status;
    char buf[255];
    char *pwd = NULL;

    pwd = getcwd(buf,255);

    if (NULL == pwd)
    {
        perror("getcwd");
    }

    printf("当前路径: %s\n",buf);
    return 0;
}

结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-you2MwmC-1641384335355)(C:\Users\纵横四海\AppData\Roaming\Typora\typora-user-images\image-20220103201025484.png)]

2.4 get_current_dir_name

函数功能:获取当前所在路径 (注意:使用时要在第一行加上#define _GNU_SOURCE)

函数原型:char *get_current_dir_name(void);

头文件:#include<unistd.h>

参数: 无

返回值:成功返回路径,失败返回NULL

#define _GNU_SOURCE
#include<stdio.h>
#include<unistd.h>

#define U8 unsigned char

int main(void)
{
    U8 status;
    char *pwd = NULL;
    pwd = get_current_dir_name();

    if (NULL == pwd)
    {
        perror("getcwd");
    }

    printf("当前路径: %s\n",pwd);
    return 0;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ixURy2Fk-1641384335356)(C:\Users\纵横四海\AppData\Roaming\Typora\typora-user-images\image-20220103201939480.png)]

2.5 chmod

功能:更改文件权限

函数原型:int chmod(const char *path, mode_t mode);

所属头文件: #include <sys/types.h>

				  #include <sys/stat.h>

参数:path:文件路径

​ mode:权限

返回值:成功返回0,失败返回-1

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


int main()
{
    char status;
    status = chmod("test.txt",0666);
    if (status < 0)
    {
        perror("chdir");
    }



    return 0;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CpBmWOMT-1641384335357)(C:\Users\纵横四海\AppData\Roaming\Typora\typora-user-images\image-20220103221122265.png)]

2.6 opendir (和文件函数open、fopen用法类似)

功能:打开目录

函数原型:DIR *opendir(const char *name);

所属头文件:

		\#include <sys/types.h>

		\#include <dirent.h>

参数:目录的路径

返回值:成功返回指向当前目录的指针,错误返回NULL

/* 我们不用关心DIR指针的内部实现,就像我们不用关心FILE指针一样 */

typedef struct __dirstream DIR; 
    struct __dirstream
   {
        void *__fd; /* `struct hurd_fd' pointer for descriptor.   */
        char *__data; /* Directory block.   */
        int __entry_data; /* Entry number `__data' corresponds to.   */
        char *__ptr; /* Current pointer into the block.   */
        int __entry_ptr; /* Entry number `__ptr' corresponds to.   */
        size_t __allocation; /* Space allocated for the block.   */
        size_t __size; /* Total valid data in the block.   */
        __libc_lock_define (, __lock) /* Mutex lock for this structure.   */
   };

2.7 closedir (和 文件关闭函数close、fclose类似)

函数功能:关闭目录

函数头文件:

 \#include <sys/types.h>

   \#include <dirent.h>

函数原型:int closedir(DIR *dir);

函数参数: DIR *dir:目录流指针

函数返回值:成功返回0 ,失败返回-1

2.8 readdir (和 文件读函数 read、fread类似)

函数功能: 读取目录文件,目录中的文件信息(文件名、扩展名等等)

函数头文件:

 \#include <sys/types.h>

  \#include <dirent.h>

函数原型: struct dirent *readdir(DIR *dirp);

函数参数: DIR *dirp:目录流指针

函数返回值:成功返回:指向存放目录相关信息的结构体指针 , 失败:返回NULL

struct dirent结构体
//  存储目录中的文件信息(文件名、扩展名等等)
#include<dirent.h>
struct dirent
{
   long d_ino; /* inode number 索引节点号 */
   off_t d_off; /* offset to this dirent 在目录文件中的偏移 */
   unsigned short d_reclen; /* length of this d_name 文件名长 */
   unsigned char d_type; /* the type of d_name 文件类型 */
   char d_name [NAME_MAX+1]; /* file name (null-terminated) 文件名,最长255字符 */
}

2.6、2.7、2.8 示例代码:

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


int main()
{
    char status;
    DIR* mydir;
    struct dirent * mydirent;

    mydir = opendir("test");
    if (NULL == mydir)
    {
        perror("opendir");
    }
    // mydirent = readdir(mydir);
    
    while ((mydirent = readdir(mydir)) != NULL)
    {
        printf("索引节点号: %lu\n",mydirent->d_ino);
        printf("在目路文件中的偏移: %ld\n",mydirent->d_off);
        printf("文件名长度: %d\n",mydirent->d_reclen);
        printf("文件类型: %d\n",mydirent->d_type);
        printf("文件名: %s\n",mydirent->d_name);
        printf("**************************************\n");
    }
    
    status = closedir(mydir);
    if (status < 0)
    {
        perror("closedir");
    }
    return 0;
}

结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Fnf2uE4G-1641384335358)(C:\Users\纵横四海\AppData\Roaming\Typora\typora-user-images\image-20220103233911275.png)]

2.9.0 rewinddir

功能:重新定位到目录文件的头部 ( 相当于文件里的读写位置 )

函数原型:void rewinddir(DIR *dir);

所属头文件:

			\#include <sys/types.h>

			\#include <dirent.h>

参数:打开目录后返回的文件指针

返回值:无

2.9.1 seekdir

功能:设置参数dir 目录流目前的读取位置, 在调用readdir()时便从此新位置开始读取. 参数offset 代表距离目录文件开头的偏移量。

函数原型:void seekdir(DIR *dir,off_t offset);

所属头文件

				\#include <sys/types.h>

				\#include <dirent.h>

参数: DIR *dir: 打开目录后返回的文件指针

		offset :代表距离目录文件开头的偏移量

返回值:无

2.9.2 telldir

功能:取得目录流的读取位置

函数原型:off_t telldir(DIR *dir);

所属头文件:

		 #include <sys/types.h>

		 #include <dirent.h>

参数:DIR *dir :打开目录后返回的文件指针

返回值:成功返回距离目录文件开头的偏移量返回值返回下个读取位置, 有错误发生时返回-1

2.9.0、2.9.1、2.9.2 示例代码:

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

int main()
{
    char status;
    DIR* mydir = NULL;
    struct dirent * mydirent = NULL;

    mydir = opendir("./test");
    if (NULL == mydir)
    {
        perror("opendir");
    }

    // mydirent = readdir(mydir);

    while ((mydirent = readdir(mydir)) != NULL)
    {
        printf("索引节点号: %lu\n",mydirent->d_ino);
        printf("在目路文件中的偏移: %ld\n",mydirent->d_off);
        printf("文件名长度: %d\n",mydirent->d_reclen);
        printf("文件类型: %d\n",mydirent->d_type);
        printf("文件名: %s\n",mydirent->d_name);
        printf("**************************************\n");
    }

    rewinddir(mydir);
    printf("使用rewinddir之后,目录指针指向目录文件开头\n");

    while ((mydirent = readdir(mydir)) != NULL)
    {
        printf("索引节点号: %lu\n",mydirent->d_ino);
        printf("在目路文件中的偏移: %ld\n",mydirent->d_off);
        printf("文件名长度: %d\n",mydirent->d_reclen);
        printf("文件类型: %d\n",mydirent->d_type);
        printf("文件名: %s\n",mydirent->d_name);
        printf("*************************\n");
    }

    status = closedir(mydir);
    if (status < 0)
    {
        perror("closedir");
    }
    return 0;
}

结果:

在这里插入图片描述

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值