我们在前面已经学习了文件的类型,主要有5类7个:普通文件(-),目录文件(d),管道文件(p),连接文件(l),设备文件:(字符设备文件c,块设备文件b,套接字s)。我们今天来学习如何获取文件属性和判断文件类型,主要的方法就是三个函数。
一、stat函数&命令
(一)获取文件属性
stat函数用来获取Linux文件的属性,头文件为 #include <sys/stat.h>,详细信息如下:
1.stat函数原型:
int stat(const char*pathname,struct stat *buf)
2.stat函数参数:
- pathname:文件的绝对路径或相对路径。
- stat类型的结构体指针,可以保存文件的所有信息,使用前必须要进行初始化,即调用stat函数进行初始化。我们用man 2 stat详细看一下struct stat 结构体的成员和含义:
struct stat{
dev_t st_dev; //文件设备编号
ino_t st_ino; //文件节点
mode_t st_mode; //文件的类型和权限
nlink_t st_nlink; //连接到该文件的硬链接(类似文件别名)数目,刚建立的文件值为1
uid_t st_uid; //用户ID
gid_t st_gid; //组ID
dev_t st_rdev; //若文件为设备文件,则为其设备编号
off_t st_size; //文件字节数(文件大小)
blksize_t st_blksize; //块大小,文件I/O缓冲区的大小
blkcnt_t st_blocks; //块数
time_t st_atime; //最后一次访问时间
time_t st_mtime; //最后一次修改时间
time_t st_ctime; //最后一次改变属性的时间
- 返回值:成果返回0,出错返回-1。
3.利用stat函数输出一个文件的所有属性:
我们可以写一段代码,将stat结构体中的成员变量进行输出。那么代码部分如下:
# include<stdio.h>
# include<stdlib.h>
# include<unistd.h>
# include<assert.h>
# include<sys/stat.h>
int main()
{
struct stat st;
int n=stat("/home/Gripure/Desktop/review/stat/showstat.c",&st);
if(n==-1)
{
perror("stat fail");
exit(0);
}
printf("文件大小:%d\n",st.st_size);
printf("文件设备:%d\n",st.st_dev);
printf("文件块:%d\n",st.st_blocks);
printf("文件节点:%d\n",st.st_ino);
printf("文件硬链接:%d\n",st.st_nlink);
printf("UID:%d\n",st.st_uid);
printf("GID:%d\n",st.st_gid);
exit(0);
}
运行结果:
(二)stat命令
stat命令和函数的作用一样,都是显示一个文件的状态信息,只不过一个在代码中实现,一个在终端上实现。
1.stat函数用法:
stat filename //显示filename的所有详细信息,可以为普通文件,设备文件等
2.选项:
stat后面可以加不同的选项,显示一个文件的不同信息,可以添加的选项和示例如下表所示:
选项 | 含义 | 示例 |
---|---|---|
-f | 显示文件系统的信息 | stat -f main.c //显示文件系统的详细信息 |
* | 查看该目录下的所有文件和子目录详细信息 | stat * |
-t | 以简洁的方式输出 | stat -t main.c //简洁输出文件信息 |
3.示例演示:
简短显示:
(三)判断文件类型
1.文件类型:
在stat结构体中有一个成员变量为mode_t st_mode,表示文件类型和权限,它是一个16位short类型的变量,对应16个标志位,组成如下:
Linux的<sts/stat.h>头文件为我们提供了一系列的文件类型宏,可以用man 2 stat查看帮助文档,方便我们进行判断文件类型,具体如下:
宏 | 文件类型 |
---|---|
S_ISREG() | 普通文件 |
S_ISDIR() | 目录文件 |
S_ISCHR() | 字符特殊文件 |
S_ISBLK() | 块特殊文件 |
S_ISFIFO() | 管道或FIFO |
S_ISLNK() | 符号链接 |
S_ISSOCK() | 套接字 |
S_IFMT | 掩码。过滤st_mode中除文件类型以外的信息 |
2.判断文件类型:
有两种方法可以判断文件类型:
- 通过类型判断函数判断:
文件类型宏(st_mode) //判断是否为这个类型的文件,是返回1,否则返回0
如: S_ISREG(st_mode)//判断是否为普通文件;其他的文件类型判断一样:
- 通过掩码过滤,进行if判断:
先利用S_IFMT过滤st_mode中除文件类型以外的信息,即得到文件类型,再判断。
if((st.st_mode & S_IFMT)==文件类型宏 )//判断文件类型是否为这个文件类型宏类型的文件,是返回1,否则返回0
如:if((st.st_mode & S_IFMT)==S_ISREG)//判断是否为普通文件。
(三)判断文件权限
st_mode中也包含了文件访问权限位,所以我们可以根据st_mode变量来判断文件权限,首先我们先了解常用的文件权限表示方式:
st_mode屏蔽 | 含义 |
---|---|
S_IRUSR | 用户读 |
S_IWUSR | 用户写 |
S_IXUSR | 用户执行 |
S_IRGRP | 组读 |
S_IWGRP | 组写 |
S_IXGRP | 组执行 |
S_IROTH | 其他读 |
S_IWOTH | 其他写 |
S_IXOTH | 其他执行 |
普通文件的读,写,执行就是字面的意思,但是目录文件却不是,它的含义是:
(1)读权限。读权限允许我们通过opendir()函数读取目录,进而可以通过readdir()函数获得目录内容,即目录下的文件列表。
(2)写权限。写权限代表的是可在目录内创建、删除文件,而不是指的写目录本身。
(3)执行权限。可访问目录中的文件。
文件权限的判断和文件类型判断方式很像,和st_mode中的数值进行与运算即可,判断对应位是否一致:
if(st.st_mode &文件权限宏) //判断该文件用户是否对应宏描述的权限
如st.st_mode & S_IXUSR判断该文件是否有用户执行权限。
二、fstat,lstat函数&三者的区别
1.fstat函数:
int fstat(int fd,struct stat *buf)
fd为文件描述符,buf即stat类型的结构体,和stat函数一样。成功返回0,出错返回-1。
2.lstat函数:
int lstat(const char*pathname,struct stat *buf)
参数和返回值和stat一样。
3.三者的区别:
- fstat函数:传递一个文件描述符,其他两个需要传入文件路径,文件描述符是我们open打开文件才会有,而文件路径可以直接写。
- lstat函数:当我们用ln -s 去软链接一个文件时,如果用stat 去查看这个链接文件的属性,则它指向的是链接文件指向的原文件的属性;而用lstat 则可以读取到链接文件本身的属性。
加油哦!💪。