用途:只有在能够用代码分析文件的属性之后,你才写出寻找linux下的一些符合某些特征的文件并对其进行操作的代码。
获取文件属性:
建议看本文前,先对linux的俩种文件IO方式做一定了解。链接:
如果你使用过Linux命令ls -l ,你一定对下图有一定的熟悉感:
我们一行行一行看,每一个蓝色标识的文件名(不同的linux颜色不一定一样)前白色的一行就包含该文件的属性。(linux下一切皆文件,目录本质也是一个文件)这些属性从左到右分别对应着:
文件类型(d) ,文件权限(rwxr-xr-x),文件硬链接数(2),用户ID(root),组ID(root),文件大小(4096) ,最后修改日期 (9月 ......);
我们在写代码的时候想获取文件的属性怎么做呢?
得先建立一个概念,这些属性一定是保存在一个和文件的属性相关的结构体中的,我们需要到文件对应的结构体中将这些信息读出来。
在linux/Unix中文件的属性信息,用结构体struct stat来表示的,其
内容为:
struct stat {
dev_t st_dev; //dev_t设备号类型,容纳该文件的那个设备的设备号
ino_t st_ino; //inode number
mode_t st_mode; //文件权限(包含类型)
nlink_t st_nlink; //Inode硬链接数
uid_t st_uid; //文件属主的用户ID
gid_t st_gid; //文件属主的组ID
dev_t st_rdev; //设备号(如果该文件是设备文件)
off_t st_size; //文件内容的长度
//st_size对普通文件(二进制文件,文本文件)指文件内容长度
//st_size对目录而言,文件长度通常是一个数的倍数
//st_size对符号链接文件,符号链接文件的内容是他指向的文件的名字
blksize_t st_blksize; //block size 块大小(与具体的硬件有关)
blkcnt_t st_blocks; //文件占多少块(在linux下面每个块是512字节)
struct timespec st_atim; //最近访问"文件内容"的时间,read/write
struct timespec st_mtim; //最近修改"文件内容"的时间
struct timespec st_ctim; //最近改变"文件属性"的时间
//printf("%s\n",ctime(&(st.st_mtim))); #include <time.h>
st_mode包含了文件的类型与权限,我们可以用下列的宏来解析
S_ISREG(st_mode) 为真,表示为普通文件(regular file) -
S_ISDIR(st_mode) 为真,表示为目录文件(directory) d
S_ISCHR(st_mode) 为真,表示为字符设备文件(char) c
S_ISBLK(st_mode) 为真,表示为块设备文件(block) b
S_ISFIFO(st_mode) 为真,表示为管道文件(pipe) p
S_ISLNK(st_mode) 为真,表示符号链接文件(link) l
S_ISSOCK(st_mode) 为真,表示套接字文件(socket) s
判断文件的权限位,我们可以用下列的宏来解析
S_IRUSR S_IWUSR S_IXUSR
S_IRGRP S_IWGRP S_IXGRP
S_IROTH S_IWOTH S_IXOTH
};
在获取属性前之前先来大致了解一些文件属性相关的API,不用看得特别仔细,关键结合后续代码演示理解。
1. stat, fstat, lstat, fstatat ----used to get file status。
SYNOPSIS(调用API所需的头文件)
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
stat用来把pathname指定的文件(包含目录,设备文件等)的状态及属性信息
保存到statbuf指向的结构体变量中去。
fstat与stat的功能类似,只不过该函数使用文件描述符来指定文件
lstat与stat的功能类似,只不过pathname指定的文件是符号链接文件时,
stat它获取的文件是该符号链接文件指向的文件的属性,而lstat获取
的是符号链接文件它本身的属性
int stat(const char *pathname, struct stat *statbuf);
int fstat(int fd, struct stat *statbuf);
int lstat(const char *pathname, struct stat *statbuf);
以及其它一些API,关于一些测试文件权限,改变文件权限,改变工作路径,删除文件或目录的。
这里是这些API的链接。--- 链接待补 ---
简单的示例代码:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
struct stat statbuf; //定义一个属性结构体,用来保存文件的属性。
//-rw-rw-r-- 1 1000 1000 6 7月 28 16:39 1.txt
// 硬链接数 用户ID 组ID 文件大小 修改时间 文件名
int main()
{
int fd = open("1.txt",O_RDWR); //首先打开文件
if(fd == -1)
{
perror("open 1.txt failed");
return -1;
}
int r = fstat(fd, &statbuf); //调用文件属性相关的API获取文件属性
if(r == -1)
{
perror("fstat 1.txt failed");
return -1;
}
switch (statbuf.st_mode & S_IFMT) //用上提到的宏解析文件类型
{
case S_IFBLK:
putchar('b');break;
case
S_IFCHR:
putchar('c');break;
case S_IFDIR:
putchar('d');break;
case S_IFIFO:
putchar('p');break;
case S_IFLNK:
putchar('l');break;
case S_IFREG:
putchar('-');break;
case S_IFSOCK:
putchar('s');break;
default:
printf("unknown?\n"); break;
}
if(statbuf.st_mode & S_IRUSR) //用上提到的宏解析文件权限
{
putchar('r');
}
else
{
putchar('-');
}
//...
printf("%4ld",statbuf.st_nlink);//打印硬链接数
printf("%5d",statbuf.st_uid);//打印用户ID
printf("%5d",statbuf.st_gid);//打印组ID
putchar('\n');
}