Linux系统下文件与目录操作
在Linux系统中有一句话叫做,一切皆文件。上节我们说的I/O操作,对于普通I/O操作,都是打开、读写、关闭。这节我们通过stat结构体来了解文件的一些基本信息和本质特征。
1. 获取文件信息
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *path, struct stat *buf);
功能:返回path文件的信息结构体(我们使用的ls -l 就是调用stat函数)
参数:path:文件名
buf:struct stat结构体指针,保存信息
返回值:成功:0,失败:-1
int fstat(int fd, struct stat *buf);
功能:返回fd的文件信息结构体
参数:path:文件名
buf:struct stat结构体指针,保存信息
返回值:成功:0,失败:-1
int lstat(const char *path, struct stat *buf);
功能:返回path文件(符号链接)的信息结构体
参数:path:文件名
buf:struct stat结构体指针,保存信息
返回值:成功:0,失败:-1
struct stat {
dev_t st_dev; /* 文件的设备编号 */
ino_t st_ino; /* 文件的inode号 */
mode_t st_mode; /* 文件权限 */
nlink_t st_nlink; /* 硬连接的数量 */
uid_t st_uid; /* 用户ID */
gid_t st_gid; /* 组ID */
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* 文件大小I/O文件 */
blksize_t st_blksize; /*文件区块大小 */
blkcnt_t st_blocks; /* 占用文件区块的个数 */
time_t st_atime; /* 文件最后一次访问时间 */
time_t st_mtime; /* 文件数据最后一次修改时间 */
time_t st_ctime; /* i节点状态最后一次更改时间 */
};
2. 文件类型
在Linux系统下有七种文件类型 bcd-lsp,最常见的是普通文件和目录。
b:块设备文件(驱动) 就是存储数据以供系统存取的接口设备,简单而言就是硬盘,每次访问以固定长度为单位。例如一号硬盘的代码是 /dev/hda1等文件。
c:字符设备文件(驱动) 这种类型文件提供对设备不带缓冲的访问,每次访问可变,即串行端口的接口设备,例如键盘、鼠标等等.系统中所有设备不是字符设备文件就是块设备文件。
d:目录文件: 就是目录,这种文件包含了其他文件的名字以及指向这些文件有关信息的指针,只有内核可以写目录文件其余只能读。
-:普通文件: Linux中最多的一种文件类型, 包括 纯文本文件(ASCII);二进制文件(binary);数据格式的文件(data);各种压缩文件.
l:链接文件 类似Windows下面的快捷方式。
s:套接字文件 这类文件通常用在网络数据连接。可以启动一个程序来监听客户端的要求,客户端就可以通过套接字来进行数据通信。最常在 /var/run目录中看到这种文件类型
p:管道文件 FIFO也是一种特殊的文件类型,它主要的目的是,解决多个程序同时存取一个文件所造成的错误。FIFO是first-in-first-out(先进先出)的缩写。
st_mode成员
文件类型
S_ISREG(m) 普通文件
S_ISDIR(m) 目录文件
S_ISCHR(m) 字符设备文件
S_ISBLK(m) 块文件
S_ISFIFO(m) 管道文件
S_ISLNK(m) 符号链接文件
S_ISSOCK(m) 套接字
文件权限
S_IRUSR 00400 用户读
S_IWUSR 00200 用户写
S_IXUSR 00100 用户可执行
S_IRGRP 00040 组读
S_IWGRP 00020 组写
S_IXGRP 00010 组执行
S_IROTH 00004 其他读
S_IWOTH 00002 其他写
S_IXOTH 00001 其他执行
S_IRWXU 00700 用户读、写、执行
S_IRWXG 00070 组读、写、执行
S_IRWXO 00007 其他读、写、执行
测试文件权限
#include <unistd.h>
int access(const char *pathname, int mode);
功能:按实际用户ID和实际组ID进行访问测试
参数:path:文件名
mode: R_OK
W_OK
X_OK
返回值:成功:0 失败:-1.
3. 屏蔽字
当一个进程创建一个新文件和目录时候,一定会使用文件模式创建屏蔽字
#include <sys/types.h>
#include <sys/stat.h>
mode_t umask(mode_t mask);
功能:进程设置文件模式创建屏蔽字(同命令umask)
参数: cmask:上面列出的就跟文件权限值(S_IRUSR等)可以‘或’
返回值:并返回之前的文件模式创建屏蔽字值
4. 修改文件权限
#include <sys/stat.h>
int chmod(const char *path, mode_t mode);
功能:修改文件权限(同命令)
参数:path:文件名
mode:权限
返回值:成功:0,失败:-1
int fchmod(int fd, mode_t mode);
功能:修改文件权限
参数:fd:打开的文件描述符
mode:权限
返回值:成功:0,失败:-1
#include <unistd.h>
int chown(const char *path, uid_t owner, gid_t group);
功能:修改文件用户ID和组ID(同命令)
参数:path:文件名
owner:用户ID
group:组ID
返回值:成功:0,失败:-1
int fchown(int fd, uid_t owner, gid_t group);
功能:修改文件用户ID和组ID(同命令)
参数:fd:打开的文件描述符
owner:用户ID
group:组ID
返回值:成功:0,失败:-1
int lchown(const char *path, uid_t owner, gid_t group);
功能:更改符号链接本身的所有者
参数:path:文件名
owner:用户ID
group:组ID
返回值:成功:0,失败:-1
5. 文件截断
#include <unistd.h>
#include <sys/types.h>
int truncate(const char *path, off_t length);
功能:截断文件
参数:path:文件名
int ftruncate(int fd, off_t length);
参数:fd:打开的文件描述符
length:将一个文件长度截断为length。如果之前文件大于length,则截断之后超出length部分无法访问,如果小于length,则后面填充0,形成空洞文件。
返回值:成功:0,失败:-1
6. 链接文件
每一个文件都可以创建一个指向该文件的链接,只有解除完该文件的链接,才能真正删除该文件。
include <unistd.h>
int link(const char *oldpath, const char *newpath);
功能:创建一个硬链接,要求在同一文件系统中。
参数:oldpath:文件名
newpath:新建链接文件名
返回值:成功:0,失败:-1,如果newpath已经存在,则返回错误。
int symlink(const char *oldpath, const char *newpath);
功能:创建一个软链接,可以在不同文件系统中
参数:oldpath:文件名
newpath:新建链接文件名
返回值:成功:0,失败:-1,如果newpath已经存在,则返回错误。
#include <unistd.h>
int unlink(const char *pathname);
功能:解除一个链接
参数:oldpath:文件名
返回值:成功:0,失败:-1,如果newpath已经存在,则返回错误。
#include <stdio.h>
int remove(const char *pathname);
功能:解除一个文件或者目录链接,等同于rmdir
参数:pathname:文件名
返回值:成功:0,失败:-1,如果newpath已经存在,则返回错误。
7. 文件重命名
#include <stdio.h>
int rename(const char *oldpath, const char *newpath);
功能:文件重命名
参数:oldpath:旧文件名
newpath:新文件名
返回值:成功:0,失败:-1,如果newpath已经存在,则先删掉oldpat再将命名为newpath。
8. 更改文件时间
一个文件的访问和修改时间可以使用以下函数来指定时间戳
#include <sys/stat.h>
struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
int utimensat(int dirfd, const char *pathname,
const struct timespec times[2], int flags);
功能:根据文件修改文件的时间戳
参数:fd:文件描述符
times:NULL: 修改为当前时间
指向timespec的指针,tv_nsec字段为UTIME_NOW,修改为当前时间,忽略tv_sec
tv_nsec字段为UTIME_OMUT,保持不变,忽略tv_sec
tv_nsec字段不是UTIME_OMUT和UTIME_NOW,则修改为设置时间
flag:AT_SYMLINK_NOFOLLOW:同时修改链接文件时间
返回值:成功:0,失败:-1
int futimens(int fd, const struct timespec times[2]);
功能:根据文件描述符修改文件的时间戳
参数:fd:文件描述符
times:NULL: 修改为当前时间
指向timespec的指针,tv_nsec字段为UTIME_NOW,修改为当前时间,忽略tv_sec
tv_nsec字段为UTIME_OMUT,保持不变,忽略tv_sec
tv_nsec字段不是UTIME_OMUT和UTIME_NOW,则修改为设置时间
返回值:成功:0,失败:-1
9. 创建目录
#include <sys/stat.h>
#include <sys/types.h>
int mkdir(const char *pathname, mode_t mode);
功能:创建一个目录
参数:pathname:目录名字
mode:权限
返回值:成功:0,失败:-1
int rmmkdir(const char *pathname, mode_t mode);
功能:删除一个目录(需要写和执行权限)
参数:pathname:目录名字
返回值:成功:0,失败:-1
10. 读目录
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);
功能:打开一个目录
参数:pathname:目录名字
返回值:成功:返回指向DIR指针,失败:null
DIR *fdopendir(int fd)
功能:通过文件描述符打开一个目录
参数:fd:将打开的文件描述符转换为目录处理函数
返回值:成功:返回指向DIR指针,失败:null
truct dirent {
ino_t d_ino; /* inode number */
off_t d_off; /* 下一个文件偏移量 */
unsigned short d_reclen; /* 文件名长度*/
unsigned char d_type; /* 文件类型 */
char d_name[256]; /* 文件名 */
};
d_type:
DT_BLK This is a block device.
DT_CHR This is a character device.
DT_DIR This is a directory.
DT_FIFO This is a named pipe (FIFO).
DT_LNK This is a symbolic link.
DT_REG This is a regular file.
DT_SOCK This is a UNIX domain socket.
DT_UNKNOWN The file type is unknown.
struct dirent *readdir(DIR *dirp);
功能:读一个目录
参数:dirp:opendir返回的指针
返回值:成功:返回指向DIR指针,失败:null
int closedir(DIR *dirp);
功能:读一个目录
参数:dirp:opendir返回的指针
返回值:成功:0,失败:-1
void rewinddir(DIR *dirp);
功能:重置opendir返回的指针读取的位置,将所读文件恢复到开头
参数:dirp:opendir返回的指针