文章目录
- 相关函数
- stat结构体
- st_mode判断文件类型的方法
- 掩码方式
- 宏方式
- 获取访问权限
- 例程:获取文件夹中文件的信息
- 例程:获取文件夹下所有文件的信息
- 在Linux系统中,我们可以使用stat、lstat和fstat函数来获取文件的属性
相关函数
- 头文件
#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>
- 函数原型:
int stat(const char *path, struct stat *buf);- 获取路径名指向的文件的信息、文件的状态,会跟随获取符号链接文件
int lstat(const char *path, struct stat *buf);- 与stat()相同,不会跟随获取符号链接文件(如果路径名是一个符号链接,那么它将返回关于链接本身的信息,而不是链接引用的文件)
int fstat(int fd, struct stat *buf);- 与stat()相同,只是要检索的信息是由文件描述符fd指定的
- 返回值:
- 成功时返回0
- 出错时返回EOF,并将errno设置为指示该错误信息
如果path是符号链接,则stat获取的是目标文件的属性,而lstat获取的是链接文件的属性
stat结构体
structstat{dev_tst_dev;//文件的设备编号ino_tst_ino;//节点mode_tst_mode;//文件的类型和存取的权限nlink_tst_nlink;//连到该文件的硬连接数目,刚建立的文件值为1uid_tst_uid;//用户IDgid_tst_gid;//组IDdev_tst_rdev;//(设备类型)若此文件为设备文件,则为其设备编号off_tst_size;//文件字节数(文件大小)unsignedlongst_blksize;//块大小(文件系统的I/O 缓冲区大小)unsignedlongst_blocks;//块数time_tst_atime;//最后一次访问时间time_tst_mtime;//最后一次修改时间time_tst_ctime;//最后一次改变时间(指属性)};由于性能和简单性考虑,stat结构中的不同字段可能包含来自执行系统调用期间的不同时刻的状态信息。例如,如果通过调用st_mode或st_uid时,其他进程调用chmod (2)或chown (2)被更改,stat()可能会与新st_uid一起返回旧st_mode,或返回旧st_uid和新st_mode
- 【mode_t】16位
- 对于权限位,在哪一位置1就代表拥有哪个权限,比如6-8位置为101,表示用户对该文件具有读权限和执行权限没有写权限
- 对于文件类型标志位,与类型掩码S_IFMT相与得到文件类型,比如0100表示目录,即S_IFDIR所代表的004
st_mode判断文件类型的方法
掩码方式
- 第一种是掩码的方式,通过系统提供的宏来判断文件类型:
S_IFMT 0170000 文件类型的位字段的位掩码 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 管道- 从S_IFSOCK到S_IFIFO是7种文件类型,S_IFMT是文件类型的掩码,通过和S_IFMT的与运算,可以把标识文件类型的位保留下来
宏方式
- 第二种是使用提供的宏来判断文件类型
S_ISREG(st_mode) 0100000 是否常规文件 S_ISDIR(st_mode) 0040000 是否目录 S_ISCHR(st_mode) 0020000 是否字符设备 S_ISBLK(st_mode) 0060000 是否块设备 S_ISFIFO(st_mode) 0010000 是否FIFO文件 S_ISLNK(st_mode) 0120000 是否链接文件 S_ISSOCK(st_mode) 0140000 是否SOCKET文件获取访问权限
- 通过系统提供的宏来获取文件访问权限(4位掩码,第一个0表示8进制):
S_IRWXU 00700 mask for file owner permissions S_IRUSR 00400 bit:8 所有者有读权限 S_IWUSR 00200 bit:7 所有者拥有写权限 S_IXUSR 00100 bit:6 所有者拥有执行权限 S_IRWXG 00070 mask for group permissions S_IRGRP 00040 bit:5 群组拥有读权限 S_IWGRP 00020 bit:4 群组拥有写权限 S_IXGRP 00010 bit:3 群组拥有执行权限 S_IRWXO 00007 mask for permissions for others (not in group) S_IROTH 00004 bit:2 其他用户拥有读权限 S_IWOTH 00002 bit:1 其他用户拥有写权限 S_IXOTH 00001 bit:0 其他用户拥有执行权限例程:获取文件夹中文件的信息
#include<stdio.h>#include<sys/types.h>#include<sys/stat.h>#include<unistd.h>#include<fcntl.h>#include<time.h>intmain(intargc,constchar*argv[]){if(argc<2){printf("Usage:%s <filename>\n",argv[1]);return-1;}structstatst;#if1// 使用stat获取文件属性if(stat(argv[1],&st)==-1){perror("stat");return-1;}#elif0// 使用lstat获取文件属性if(lstat(argv[1],&st)==-1){perror("lstat");return-1;}printf("file size:%ld\n",st.st_size);#else// 使用fstat获取文件属性intfd=open(argv[1],O_RDONLY);if(fd<0){perror("open");return-1;}fstat(fd,&st);printf("file size:%ld\n",st.st_size);#endif//输出文件类型switch(S_IFMT&st.st_mode){caseS_IFREG:putchar('-');break;caseS_IFDIR:putchar('d');break;caseS_IFSOCK:putchar('s');break;caseS_IFLNK:putchar('l');break;caseS_IFBLK:putchar('b');break;caseS_IFCHR:putchar('c');break;caseS_IFIFO:putchar('f');break;default:printf("have a failed\n");return-1;}//输出当前用户对文件的权限intn=8;do{if(st.st_mode&(0x1<<n)){switch(n%3){case0:putchar('x');break;case1:putchar('w');break;case2:putchar('r');break;}}else{putchar('-');}}while(n--);//输出文件的字节大小printf("\t%ld",st.st_size);//输出文件的最后修改时间printf("\t%s",ctime(&st.st_ctime));return0;}例程:获取文件夹下所有文件的信息
- 获取当前文件夹内容,并显示其中文件的属性(展示效果类似于ls -al)以下面格式打印指定文件的主要信息
user@linux-mac:~$./a.out xxxdir aaa.c -rw-rw-r--635Mon Nov1117:55:242024bbb.c -rw-rw-r--151Thu Oct1710:21:252024ccc.c -rw-rw-r--972Tue Oct815:09:052024ddd.c -rw-rw-r--180Fri Oct1810:56:372024#include<stdio.h>#include<dirent.h>#include<sys/types.h>#include<sys/stat.h>#include<unistd.h>#include<string.h>#include<time.h>intmain(intargc,constchar*argv[]){if(argc<2){printf("Usage: <%s> <filename>\n",argv[0]);return-1;}DIR*dirp=NULL;structdirent*dp=NULL;structstatst;chardirpath[30]="./";strcat(dirpath,argv[1]);charfilename[30]={0};intn;if((dirp=opendir(dirpath))==NULL){perror("opendir");return-1;}while((dp=readdir(dirp))!=NULL){if(!strcmp(dp->d_name,".")||!strcmp(dp->d_name,"..")){continue;}//输出文件名printf("%-30s\t",dp->d_name);// 使用lstat获取文件属性sprintf(filename,"%s%s%s",dirpath,"/",dp->d_name);if(lstat(filename,&st)==-1){perror("lstat");return-1;}//输出文件类型switch(S_IFMT&st.st_mode){caseS_IFREG:putchar('-');break;caseS_IFDIR:putchar('d');break;caseS_IFLNK:putchar('l');break;caseS_IFSOCK:putchar('s');break;caseS_IFBLK:putchar('b');break;caseS_IFCHR:putchar('c');break;caseS_IFIFO:putchar('f');}//输出当前用户对文件的权限n=8;do{if(st.st_mode&(0x1<<n)){switch(n%3){case0:putchar('x');break;case1:putchar('w');break;case2:putchar('r');break;}}else{putchar('-');}}while(n--);//输出文件的字节大小printf("\t%10ld",st.st_size);//输出文件的最后修改时间printf("\t%30s",ctime(&st.st_ctime));}closedir(dirp);return0;}