Linux应用编程(文件属性与目录)

news2024/11/14 13:41:37

本章将会讨论如下主题内容。
⚫ Linux 系统的文件类型;
⚫ stat 系统调用;
⚫ 文件各种属性介绍:文件属主、访问权限、时间戳;
⚫ 符号链接与硬链接;
⚫ 目录;
⚫ 删除文件与文件重命名。

一、Linux 系统中的文件类型

在 Linux 系统下,可以通过 stat 命令或者 ls 命令来查看文件类型,如下所示:
在这里插入图片描述
在这里插入图片描述
其中第一个字符(’ - ‘)就用于表示文件的类型,减号’ - '就表示该文件是一个普通文件看,看其它文件类型使用什么字符表示:
⚫ ’ - ':普通文件
⚫ ’ d ':目录文件
⚫ ’ c ':字符设备文件
⚫ ’ b ':块设备文件
⚫ ’ l ':符号链接文件
⚫ ’ s ':套接字文件
⚫ ’ p ':管道文件

二、stat 函数

Linux 下可以使用 stat 命令查看文件的属性,其实这个命令内部就是通过调用 stat()函数来获取文件属性的,stat 函数是 Linux 中的系统调用。

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *pathname, struct stat *buf);

pathname:用于指定一个需要查看属性的文件路径。
buf:struct stat 类型指针,用于指向一个 struct stat 结构体变量。调用 stat 函数的时候需要传入一个 struct stat 变量的指针,获取到的文件属性信息就记录在struct stat结构体中。
返回值:成功返回 0;失败返回-1,并设置 error。

1、struct stat 结构体

struct stat
{
 dev_t st_dev; /* 文件所在设备的 ID */
 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; /* 设备号(指针对设备文件) */
 off_t st_size; /* 文件大小(以字节为单位) */
 blksize_t st_blksize; /* 文件内容存储的块大小 */
 blkcnt_t st_blocks; /* 文件内容所占块数 */
 struct timespec st_atim; /* 文件最后被访问的时间 */
 struct timespec st_mtim; /* 文件内容最后被修改的时间 */
 struct timespec st_ctim; /* 文件状态最后被改变的时间 */
};

1.1、st_mode 变量

st_mode 是 structstat 结构体中的一个成员变量,是一个 32 位无符号整形数据,该变量记录了文件的类型、文件的权限这些信息,其表示方法如下所示:

在这里插入图片描述
在 mode 参数中表示权限的宏定义如下:

S_IRWXU 	00700 	owner has read, write, and execute permission
S_IRUSR 	00400 	owner has read permission
S_IWUSR 	00200 	owner has write permission
S_IXUSR 	00100 	owner has execute permission
S_IRWXG 	00070 	group has read, write, and execute permission
S_IRGRP 	00040 	group has read permission
S_IWGRP 	00020 	group has write permission
S_IXGRP 	00010 	group has execute permission
S_IRWXO 	00007 	others (not in group) have read, write, and execute permission
S_IROTH 	00004 	others have read permission
S_IWOTH 	00002 	others have write permission
S_IXOTH 	00001 	others have execute permission

譬如,判断文件所有者对该文件是否具有可执行权限,可以通过以下方法测试(假设 st 是 structstat 类型变量):

if (st.st_mode & S_IXUSR) 
{
	//有权限
} 
else 
{
	//无权限
}

这里我们重点来看看“文件类型”这 4 个 bit 位,这 4 个 bit 位用于描述该文件的类型,譬如该文件是普通文件、还是链接文件、亦或者是一个目录等,那么就可以通过这 4 个 bit 位数据判断出来,如下所示:

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(管道文件)

我们还可以使用 Linux 系统封装好的宏来进行判断,如下所示(m 是 st_mode 变量):

S_ISREG(m) 	//判断是不是普通文件,如果是返回 true,否则返回 false
S_ISDIR(m) 	//判断是不是目录,如果是返回 true,否则返回 false
S_ISCHR(m) 	//判断是不是字符设备文件,如果是返回 true,否则返回 false
S_ISBLK(m) 	//判断是不是块设备文件,如果是返回 true,否则返回 false
S_ISFIFO(m)	//判断是不是管道文件,如果是返回 true,否则返回 false
S_ISLNK(m)	//判断是不是链接文件,如果是返回 true,否则返回 false

S_ISSOCK(m) #判断是不是套接字文件,如果是返回 true,否则返回 false有了这些宏之后,就可以通过如下方式来判断文件类型了:

/* 判断是不是普通文件 */
if (S_ISREG(st.st_mode)) {
	/* 是 */
}
/* 判断是不是目录 */
if (S_ISDIR(st.st_mode)) {
	/* 是 */
}

2、struct timespec 结构体

struct timespec
{
 time_t tv_sec; /* 秒 */
 syscall_slong_t tv_nsec; /* 纳秒 */
};

编程实战练习 1

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

int main(void)
{
	 struct stat file_stat;
	 int ret;
	 /* 获取文件属性 */
	 ret = stat("./test_file", &file_stat);
	 if (-1 == ret) 
	 {
		 perror("stat error");
		 exit(-1);
	 }
	 /* 打印文件大小和 inode 编号 */
	 printf("file size: %ld bytes\n""inode number: %ld\n", file_stat.st_size,
	 file_stat.st_ino);
	 exit(0);
}

在这里插入图片描述

编程实战练习 2

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

int main(void)
{
	 struct stat file_stat;
	 int ret;
	 /* 获取文件属性 */
	 ret = stat("./test_file", &file_stat);
	 if (-1 == ret) 
	 {
		 perror("stat error");
		 exit(-1);
	 }
	 /* 判读文件类型 */
	 switch (file_stat.st_mode & S_IFMT) 
	 {
		 case S_IFSOCK: printf("socket"); break;
		 case S_IFLNK: printf("symbolic link"); break;
		 case S_IFREG: printf("regular file"); break;
		 case S_IFBLK: printf("block device"); break;
		 case S_IFDIR: printf("directory"); break;
		 case S_IFCHR: printf("character device"); break;
		 case S_IFIFO: printf("FIFO"); break;
	 }
	 
	 printf("\n");
	 
	 /* 判断该文件对其它用户是否具有读权限 */
	 if (file_stat.st_mode & S_IROTH)
		 printf("Read: Yes\n");
	 else
		 printf("Read: No\n");
		 
	 /* 判断该文件对其它用户是否具有写权限 */
	 if (file_stat.st_mode & S_IWOTH)
		 printf("Write: Yes\n");
	 else
	 	printf("Write: No\n");
	
	 exit(0);
}

在这里插入图片描述
编程实战练习 3

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

int main(void)
{
	 struct stat file_stat;
	 struct tm file_tm;
	 char time_str[100];
	 int ret;
	 /* 获取文件属性 */
	 ret = stat("./test_file", &file_stat);
	 if (-1 == ret) 
	 {
		 perror("stat error");
		 exit(-1);
	 }
	 
	 /* 打印文件最后被访问的时间 */
	 localtime_r(&file_stat.st_atim.tv_sec, &file_tm);
	 strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", &file_tm);
	 printf("time of last access: %s\n", time_str);
	 
	 /* 打印文件内容最后被修改的时间 */
	 localtime_r(&file_stat.st_mtim.tv_sec, &file_tm);
	 strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", &file_tm);
	
	 printf("time of last modification: %s\n", time_str);
	 
	 /* 打印文件状态最后改变的时间 */
	 localtime_r(&file_stat.st_ctim.tv_sec, &file_tm);
	 strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", &file_tm);
	 printf("time of last status change: %s\n", time_str);
	 exit(0);
}

三、fstat 和 lstat 函数

1、fstat 函数

fstat 与 stat 区别在于,stat 是从文件名出发得到文件属性信息,不需要先打开文件;而 fstat 函数则是从文件描述符出发得到文件属性信息,所以使用 fstat 函数之前需要先打开文件得到文件描述符。

2、lstat 函数
lstat()与 stat、fstat 的区别在于,对于符号链接文件,stat、fstat 查阅的是符号链接文件所指向的文件对应的文件属性信息,而 lstat 查阅的是符号链接文件本身的属性信息。

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int lstat(const char *pathname, struct stat *buf);

四、文件属主

Linux 是一个多用户操作系统,系统中一般存在着好几个不同的用户,而 Linux 系统中的每一个文件都有一个与之相关联的用户和用户组,通过这个信息可以判断文件的所有者和所属组。

文件所有者表示该文件属于“谁”,也就是属于哪个用户。一般来说文件在创建时,其所有者就是创建该文件的那个用户。譬如,当前登录用户为 dt,使用 touch 命令创建了一个文件,那么这个文件的所有者就是 dt;同理,在程序中调用 open 函数创建新文件时也是如此,执行该程序的用户是谁,其文件所有者便是谁。

Linux系统通过用户 ID(UID)或组 ID(GID)就可以识别出不同的用户和用户组。
在这里插入图片描述既然 Linux 下的每一个文件都有与之相关联的用户 ID 和组 ID,那么对于一个进程来说亦是如此,与一个进程相关联的 ID 有 5 个或更多,如下表所示:
在这里插入图片描述
⚫ 实际用户 ID 和实际组 ID 标识我们究竟是谁,也就是执行该进程的用户是谁、以及该用户对应的所属组;实际用户 ID 和实际组 ID 确定了进程所属的用户和组。
⚫ 进程的有效用户 ID、有效组 ID 以及附属组 ID 用于文件访问权限检查。

1、有效用户 ID 和有效组 ID

首先对于有效用户 ID 和有效组 ID 来说,这是进程所持有的概念,对于文件来说,并无此属性!有效用户 ID 和有效组 ID 是站在操作系统的角度,用于给操作系统判断当前执行该进程的用户在当前环境下对某个文件是否拥有相应的权限。

在Linux系统中,当进行权限检查时,并不是通过进程的实际用户和实际组来参与权限检查的,而是通过有效用户和有效组来参与文件权限检查。通常,绝大部分情况下,进程的有效用户等于实际用户(有效用户 ID 等于实际用户 ID),有效组等于实际组(有效组 ID 等于实际组 ID)。

2、chown 函数

chown 是一个系统调用,该系统调用可用于改变文件的所有者(用户 ID)和所属组(组 ID)。其实在Linux 系统下也有一个 chown 命令,该命令的作用也是用于改变文件的所有者和所属组,譬如将 testApp.c文件的所有者和所属组修改为 root:

sudo chown root:root testApp.c

在这里插入图片描述
chown 函数原型如下所示

#include <unistd.h>
int chown(const char *pathname, uid_t owner, gid_t group);

函数参数和返回值如下所示:
pathname:用于指定一个需要修改所有者和所属组的文件路径。
owner:将文件的所有者修改为该参数指定的用户(以用户 ID 的形式描述);
group:将文件的所属组修改为该参数指定的用户组(以用户组 ID 的形式描述);
返回值:成功返回 0;失败将返回-1,兵并且会设置 errno。

测试

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

int main(void)
{
	 if (-1 == chown("./test_file", 0, 0)) 
	 {
		 perror("chown error");
		 exit(-1);
	 }
	 exit(0);
}

在 Linux 系统下,可以使用 getuid 和 getgid 两个系统调用分别用于获取当前进程的用户 ID 和用户组ID,这里说的进程的用户 ID 和用户组 ID 指的就是进程的实际用户 ID 和实际组 ID,这两个系统调用函数原型如下所示:

#include <unistd.h>
#include <sys/types.h>

uid_t getuid(void);
gid_t getgid(void);
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
	 printf("uid: %d\n", getuid());
	 if (-1 == chown("./test_file", 0, 0)) 
	 {
		 perror("chown error");
		 exit(-1);
	 }
	 exit(0);
}

在这里插入图片描述
很明显可以看到两次执行同一个应用程序它们的用户 ID 是不一样的,因为加上了 sudo 使得应用程序的用户 ID 由原本的普通用户 ID 1000 变成了超级用户 ID 0,使得该进程变成了超级用户进程,所以调用chown 函数就不会报错。

3、fchown 和 lchown 函数

fchown()、lchown()这两个函数与 chown()的区别就像是 fstat()、lstat()与 stat 的区别。

五、文件访问权限

struct stat 结构体中的 st_mode 字段记录了文件的访问权限位。当提及到文件时,指的是前面给大家介绍的任何类型的文件,并不仅仅指的是普通文件;所有文件类型(目录、设备文件)都有访问权限(accesspermission),可能有很多人认为只有普通文件才有访问权限,这是一种误解!

普通权限

在这里插入图片描述
譬如使用 ls 命令或 stat 命令可以查看到文件的这 9 个访问权限,如下所示:
在这里插入图片描述
在这里插入图片描述
而对于进程来说,参与文件权限检查的是进程的有效用户、有效用户组以及进程的附属组用户。
如何判断权限,首先要搞清楚该进程对于需要进行操作的文件来说是属于哪一类“角色”:
⚫ 如果进程的有效用户 ID 等于文件所有者 ID(st_uid),意味着该进程以文件所有者的角色存在;
⚫ 如果进程的有效用户 ID 并不等于文件所有者 ID,意味着该进程并不是文件所有者身份;但是进程的有效用户组 ID 或进程的附属组 ID 之一等于文件的组 ID(st_gid),那么意味着该进程以文件所属组成员的角色存在,也就是文件所属组的同组用户成员。
⚫ 如果进程的有效用户 ID 不等于文件所有者 ID、并且进程的有效用户组 ID 或进程的所有附属组 ID均不等于文件的组 ID(st_gid),那么意味着该进程以其它用户的角色存在。
⚫ 如果进程的有效用户 ID 等于 0(root 用户),则无需进行权限检查,直接对该文件拥有最高权限。

特殊权限

从高位到低位依次表示文件的 set-user-ID 位权限、set-group-ID 位权限以及 sticky 位权限,如下所示:

在这里插入图片描述

1、检查文件权限 access

#include <unistd.h>
int access(const char *pathname, int mode);

函数参数和返回值含义如下
pathname:需要进行权限检查的文件路径。
mode:该参数可以取以下值:
⚫ F_OK:检查文件是否存在
⚫ R_OK:检查是否拥有读权限
⚫ W_OK:检查是否拥有写权限
⚫ X_OK:检查是否拥有执行权限
除了可以单独使用之外,还可以通过按位或运算符" | "组合在一起。
返回值:检查项通过则返回 0,表示拥有相应的权限并且文件存在;否则返回-1,如果多个检查项组合在一起,只要其中任何一项不通过都会返回-1。

2、修改文件权限 chmod

#include <sys/stat.h>
int chmod(const char *pathname, mode_t mode);

函数参数及返回值如下所示:
pathname:需要进行权限修改的文件路径,若该参数所指为符号链接,实际改变权限的文件是符号链接所指向的文件,而不是符号链接文件本身。
mode:该参数用于描述文件权限,与 open 函数的第三个参数一样,这里不再重述,可以直接使用八进制数据来描述,也可以使用相应的权限宏(单个或通过位或运算符" | "组合)。
返回值:成功返回 0;失败返回-1,并设置 errno。

文件权限对于文件来说是非常重要的属性,是不能随随便便被任何用户所修改的,要想更改文件权限,要么是超级用户(root)进程、要么进程有效用户 ID 与文件的用户 ID(文件所有者)相匹配。

fchmod 函数
该函数功能与 chmod 一样,参数略有不同。

六、符号链接(软链接)与硬链接

在 Linux 系统中有两种链接文件,分为软链接(也叫符号链接)文件和硬链接文件,软链接文件也就是前面给大家的 Linux 系统下的七种文件类型之一,其作用类似于 Windows 下的快捷方式。
从使用角度来讲,两者没有任何区别,都与正常的文件访问方式一样,支持读、写以及执行。

使用 ln 命令可以为一个文件创建软链接文件或硬链接文件,用法如下:
硬链接:ln 源文件 链接文件
软链接:ln -s 源文件 链接文件
在这里插入图片描述
从上图中可知,使用 ln 命令创建的两个硬链接文件与源文件 test_file 都拥有相同的 inode 号,既然inode 相同,也就意味着它们指向了物理硬盘的同一个区块,仅仅只是文件名字不同而已,创建出来的硬链接文件与源文件对文件系统来说是完全平等的关系。每删除一个硬链接,inode 节点上的链接数就会减一,直到为 0,inode 节点和对应的数据块才会被文件系统所回收,也就意味着文件已经从文件系统中被删除了。

软链接文件与源文件有着不同的 inode 号,如下图所示,所以也就是意味着它们之间有着不同的数据块,但是软链接文件的数据块中存储的是源文件的路径名,链接文件可以通过这个路径找到被链接的源文件,它们之间类似于一种“主从”关系,当源文件被删除之后,软链接文件依然存在,但此时它指向的是一个无效的文件路径,这种链接文件被称为悬空链接。
在这里插入图片描述

介绍完它们之间的区别之后,大家可能觉得硬链接相对于软链接来说有较大的优势,其实并不是这样,对于硬链接来说,存在一些限制情况,如下:
⚫ 不能对目录创建硬链接(超级用户可以创建,但必须在底层文件系统支持的情况下)。
⚫ 硬链接通常要求链接文件和源文件位于同一文件系统中。
而软链接文件的使用并没有上述限制条件,优点如下所示:
⚫ 可以对目录创建软链接;
⚫ 可以跨越不同文件系统;
⚫ 可以对不存在的文件创建软链接。

1、创建链接文件

创建硬链接 link()

link()系统调用用于创建硬链接文件,函数原型如下(可通过"man 2 link"命令查看):

#include <unistd.h>
int link(const char *oldpath, const char *newpath);

oldpath:用于指定被链接的源文件路径,应避免 oldpath 参数指定为软链接文件,为软链接文件创建硬链接没有意义,虽然并不会报错。
newpath:用于指定硬链接文件路径,如果 newpath 指定的文件路径已存在,则会产生错误。返回值:成功返回 0;失败将返回-1,并且会设置 errno。

link 函数测试

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
	 int ret;
	 ret = link("./test_file", "./hard");
	 if (-1 == ret) {
		 perror("link error");
		 exit(-1);
	 }
	 exit(0);
}

程序中通过 link 函数为当前目录下的 test_file 文件创建了一个硬链接 hard,编译测试:
在这里插入图片描述
创建软链接 symlink()

#include <unistd.h>
int symlink(const char *target, const char *linkpath);

函数参数和返回值含义如下:
target:用于指定被链接的源文件路径,target 参数指定的也可以是一个软链接文件。
linkpath:用于指定硬链接文件路径,如果 newpath 指定的文件路径已存在,则会产生错误。
返回值:成功返回 0;失败将返回-1,并会设置 errno。
创建软链接时,并不要求 target 参数指定的文件路径已经存在,如果文件不存在,那么创建的软链接将成为“悬空链接”。

symlink 函数测试

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

int main(void)
{
	 int ret;
	 ret = symlink("./test_file", "./soft");
	 if (-1 == ret) 
	 {
		 perror("symlink error");
		 exit(-1);
	 }
	 exit(0);
}

在这里插入图片描述

2、读取软链接文件

#include <unistd.h>
ssize_t readlink(const char *pathname, char *buf, size_t bufsiz);

函数参数和返回值含义如下:
pathname:需要读取的软链接文件路径。只能是软链接文件路径,不能是其它类型文件,否则调用函数将报错。
buf:用于存放路径信息的缓冲区。
bufsiz:读取大小,一般读取的大小需要大于链接文件数据块中存储的文件路径信息字节大小。
返回值:失败将返回-1,并会设置 errno;成功将返回读取到的字节数。

readlink 函数测试

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(void)
{
	 char buf[50];
	 int ret;
	 memset(buf, 0x0, sizeof(buf));
	 ret = readlink("./soft", buf, sizeof(buf));
	 if (-1 == ret) 
	 {
		 perror("readlink error");
		 exit(-1);
	 }
	 printf("%s\n", buf);
	 exit(0);
}

使用 readlink 函数读取当前目录下的软链接文件 soft,并将读取到的信息打印出来,测试如下:
在这里插入图片描述

七、目录

struct dirent {
 ino_t d_ino; /* inode 编号 */
 off_t d_off; /* not an offset; see NOTES */
 unsigned short d_reclen; /* length of this record */
 unsigned char d_type; /* type of file; not supported by all filesystem types */
 char d_name[256]; /* 文件名 */
};
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/types.h>
#include <errno.h>
int main(void)
{
	 struct dirent *dir;
	 DIR *dirp;
	 int ret = 0;
	 /* 打开目录 */
	 dirp = opendir("./my_dir");
	 if (NULL == dirp) 
	 {
		 perror("opendir error");
		 exit(-1);
	 }
	 /* 循环读取目录流中的所有目录条目 */
	 errno = 0;
	 while (NULL != (dir = readdir(dirp)))
		 printf("%s %ld\n", dir->d_name, dir->d_ino);
	 if (0 != errno) 
	 {
		 perror("readdir error");
		 ret = -1;
		 goto err;
	 } 
	 else
		 printf("End of directory!\n");
	err:
	 closedir(dirp);
	 exit(ret);
}

在这里插入图片描述
在这里插入图片描述
1、进程的当前工作目录
Linux 下的每一个进程都有自己的当前工作目录(current working directory),当前工作目录是该进程解析、搜索相对路径名的起点(不是以" / "斜杆开头的绝对路径)。譬如,代码中调用 open 函数打开文件时,传入的文件路径使用相对路径方式进行表示,那么该进程解析这个相对路径名时、会以进程的当前工作目录作为参考目录。

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

int main(void)
{
	 char buf[100];
	 char *ptr;
	 
	 memset(buf, 0x0, sizeof(buf));
	 ptr = getcwd(buf, sizeof(buf));		//获取进程工作目录
	 
	 if (NULL == ptr) 
	 {
		 perror("getcwd error");
		 exit(-1);
	 }
	 printf("Current working directory: %s\n", buf);
	 exit(0);
}

在这里插入图片描述

改变当前工作目录

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

int main(void)
{
	 char buf[100];
	 char *ptr;
	 int ret;
	 /* 获取更改前的工作目录 */
	 memset(buf, 0x0, sizeof(buf));
	 ptr = getcwd(buf, sizeof(buf));
	 if (NULL == ptr) 
	 {
		 perror("getcwd error");
		 exit(-1);
	 }
	 printf("Before the change: %s\n", buf);
	 /* 更改进程的当前工作目录 */
	 ret = chdir("./new_dir");
	 if (-1 == ret) 
	 {
		 perror("chdir error");
		 exit(-1);
	 }
	 /* 获取更改后的工作目录 */
	 memset(buf, 0x0, sizeof(buf));
	 ptr = getcwd(buf, sizeof(buf));
	 if (NULL == ptr) 
	 {
		 perror("getcwd error");
		 exit(-1);
	 }
	 printf("After the change: %s\n", buf);
	 exit(0);
}

在这里插入图片描述

2、删除文件

使用 unlink 函数删除文件

#include <unistd.h>
int unlink(const char *pathname);

函数参数和返回值含义如下:
pathname:需要删除的文件路径,可使用相对路径、也可使用绝对路径,如果 pathname 参数指定的文件不存在,则调用 unlink()失败。
返回值:成功返回 0;失败将返回-1,并设置 errno。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
	 int ret;
	 ret = unlink("./test_file");
	 if (-1 == ret) {
		 perror("unlink error");
		 exit(-1);
	 }
	 exit(0);
}

在这里插入图片描述
使用 remove 函数删除文件

#include <stdio.h>
int remove(const char *pathname);
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
	 int ret;
	 ret = remove("./test_file");
	 if (-1 == ret) 
	 {
		 perror("remove error");
		 exit(-1);
	 }
	 exit(0);
}

八、文件重命名

#include <stdio.h>
int rename(const char *oldpath, const char *newpath);

函数参数和返回值含义如下:
oldpath:原文件路径。
newpath:新文件路径。
返回值:成功返回 0;失败将返回-1,并设置 errno。

根据 oldpath、newpath 的不同,有以下不同的情况需要进行说明:
⚫ 若 newpath 参数指定的文件或目录已经存在,则将其覆盖;
⚫ 若 newpath 和 oldpath 指向同一个文件,则不发生变化(且调用成功)。
⚫ rename()系统调用对其两个参数中的软链接均不进行解引用。如果 oldpath 是一个软链接,那么将重命名该软链接;如果 newpath 是一个软链接,则会将其移除、被覆盖。
⚫ 如果 oldpath 指代文件,而非目录,那么就不能将 newpath 指定为一个目录的路径名。要想重命名一个文件到某一个目录下,newpath 必须包含新的文件名。
⚫ 如果 oldpath 指代为一个目录,在这种情况下,newpath 要么不存在,要么必须指定为一个空目录。
⚫ oldpath 和 newpath 所指代的文件必须位于同一文件系统。由前面的介绍,可以得出此结论!
⚫ 不能对.(当前目录)和…(上一级目录)进行重命名。

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
	 int ret;
	 ret = rename("./test_file", "./new_file");
	 if (-1 == ret) 
	 {
		 perror("rename error");
		 exit(-1);
	 }
	 exit(0);
}

九、总结

开头先给大家介绍 Linux 系统下的 7 种文件类型,包括普通文件、目录、设备文件(字符设备文件、块设备文件)、符号链接文件(软链接文件)、管道文件以及套接字文件。
接着围绕 stat 系统调用,详细给大家介绍了 struct stat 结构体中的每一个成员,这使得我们对 Linux 下文件的各个属性都有所了解。接着分别给大家详细介绍了文件属主、文件访问权限、文件时间戳、软链接与硬链接以及目录等相关内容,让大家知道在应用编程中如何去修改文件的这些属性以及它们所需要满足的条件。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/417072.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python编写一计票程序,键盘输入候选人姓名(输入“#”结束),使用字典存储并统计出候选人得票数。python实现分段函数。

一、编程题目 编程题目1&#xff1a;python编写一计票程序&#xff0c;键盘输入候选人姓名(输入“#”结束)&#xff0c;使用字典存储并统计出候选人得票数。 编程题目2&#xff1a;python实现以下分段函数&#xff1a; y 2x^34x^23 -10<x<0 y x14 0<x<6 y 6x…

001+limou+git安装与入门

1、git安装以及下载检查&#xff08;windows环境&#xff0c;macOS可能比较麻烦&#xff09; &#xff08;1&#xff09;下载git git官网下载&#xff0c; Git - Downloading Package (git-scm.com) &#xff08;2&#xff09;检查下载 以下命令可以检查git是否下载成功 $…

JAVA入坑之类和对象

目录 一、类 1.1面向对象(OOP)与面向过程 1.2面向对象的三个特性 1.3类的语法格式 1.3.1类的分类 1.3.2类修饰符 1.4变量 1.4.1变量格式 1.4.2成员变量 1.4.3区分实例变量和类变量 1.4.4局部变量 1.4.5区分成员变量和局部变量 1.5final关键字 1.5.1常量 1.6方法 …

基于Java+SSM+jsp的二手车交易网站设计与实现【源码(完整源码请私聊)+论文+演示视频+包运行成功】

博主介绍&#xff1a;专注于Java技术领域和毕业项目实战 &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3fb; 不然下次找不到哟 Java项目精品实战案例&#xff08;300套&#xff09; 目录 一、效果演示 二、…

博客首页效果

学习来自风宇blog的博客首页效果 全部用的基本上都是原生的html&#xff0c;css&#xff0c;js特别是flex布局的使用&#xff0c;主轴方向可以是横轴&#xff0c;也可以是纵轴&#xff0c;弹性项还可可以使用百分比sticky粘性布局&#xff0c;作为侧边栏&#xff0c;它不会超出…

Spring Cloud组件源码之OpenFeign源码分析

" Spring 到底是春天的来临万物复苏&#xff0c;还是春转夏的干燥又炎热呢&#xff1f;" Spring的来临让JavaEE走向了另一个高度。便捷的开发&#xff0c;完美的生态。物极必反&#xff0c;学习Spring的成本越来越低&#xff0c;导致Java程序员越来越密集&#xff0…

实习不对口,还去吗?

作者&#xff1a;阿秀校招八股文学习网站&#xff1a;https://interviewguide.cn这是阿秀的第「255」篇原创小伙伴们大家好&#xff0c;我是阿秀。欢迎今年参加秋招的小伙伴加入我的学习圈&#xff0c;目前已经超过 2200 小伙伴加入&#xff01;去年认真准备和走下来的基本都拿…

LBS计算附近的对象:MySQL 空间索引方式

目录1. MySQL空间数据类型的基本介绍1.1 什么是MySQL空间数据类型1.2 有哪些空间数据类型1.3 支持空间数据类型的引擎1.4 坐标系类型2. 存储坐标系的示例代码2.1 geomtry和point都可以存储坐标系&#xff0c;有什么区别呢&#xff1f;2.2 创建测试表2.3 新增坐标2.3 计算两地之…

计组2.1——计算机中的数据

问题&#xff1a;数据如何在计算机中表示&#xff1f; 运算器如何进行数字运算和逻辑运算&#xff1f; 计组2.11.进制转化&#xff1a;2. BCD码3.字符和字符串1.ASCII2.汉字编码3.字符串4.奇偶校验码1. 校验原理3. 奇偶校验5.汉明码6.循环冗余校验码1.进制转化&#xff1a; #me…

【C语言】关于文件操作你知多少?

目录 一.引入 二. 什么是文件 2.1 什么是文件 2.2 程序文件 2.3 数据文件 2.4 文件名 三.文件的打开和关闭 3.1 文件指针 3.2 文件的打开和关闭 四.文件的顺序读写 4.1 函数汇总 4.2 printf/fprintf/sprintf 4.3 scanf/fscanf/sscanf 五. 文件的随机读写 5.1 引入 5.2 fsee…

HTML5 <ins> 标签、HTML5 <link> 标签

HTML5 <ins> 标签 实例 一段带有已删除部分和新插入部分的文本&#xff1a; <p>My favorite color is <del>blue</del> <ins>red</ins>!</p> 尝试一下 浏览器支持 所有主流浏览器都支持 <ins> 标签。 标签定义及使用说明 …

Sentry安装使用(最全最细)

Sentry安装使用(最全最细&#xff0c;包括解决邮箱发送问题&#xff0c;https上传问题&#xff0c;https访问问题&#xff0c;安装此教程配置即可) ##服务器操作系统为2核8G,CentOS7.9 ##安装Docker-ce yum install -y yum-utils \device-mapper-persistent-data \lvm2yum-c…

日撸 Java 三百行day27

文章目录说明day27 Hanoi 塔问题1.思路2.代码3.图示说明 闵老师的文章链接&#xff1a; 日撸 Java 三百行&#xff08;总述&#xff09;_minfanphd的博客-CSDN博客 自己也把手敲的代码放在了github上维护&#xff1a;https://github.com/fulisha-ok/sampledata day27 Hanoi 塔…

部署LAMP架构和论坛

引言 LAMP架构是目前成熟的企业网站应用模式之一&#xff0c;指的是协同工作的一整套系统和相关软件&#xff0c;能够提供动态Web站点服务及其应用开发环境。LAMP是一个缩写词&#xff0c;具体包括Linux操作系统、Apache网站服务器、MySQL数据库服务器、PHP&#xff08;或Perl、…

Win10,详细永久关闭更新方法(附图文)

一、服务设置 1.同时按下键盘 Win R&#xff0c;打开运行对话框&#xff0c;然后输入命令 services.msc &#xff0c;点击下方的“确定”打开服务。 2.找到 Windows Update 这一项&#xff0c;并双击打开。 3.停止该服务&#xff0c;启动类型设置为禁用 4.点击恢复&#…

webrtc入门系列(二)easy_webrtc_server 入门example测试

《webrtc入门系列&#xff08;一&#xff09;easy_webrtc_server 入门环境搭建》 《webrtc入门系列&#xff08;二&#xff09;easy_webrtc_server 入门example测试》 《webrtc入门系列&#xff08;三&#xff09;云服务器coturn环境搭建》 《webrtc入门系列&#xff08;四&…

好用的免费 PDF 密码删除工具有哪些?

被锁定在文档之外可能会令人沮丧&#xff0c;尤其是当唯一挡路的是一个讨厌的弹出窗口要求您输入密码时。 如果您创建了 PDF 文档或有权访问它&#xff0c;您可以尝试一些行之有效的技巧来删除密码保护。 例如&#xff0c;您可以使用网络浏览器或文档阅读器中的打印设置将 PD…

Windows权限提升—令牌窃取、UAC提权、进程注入等提权

Windows权限提升—令牌窃取、UNC提权、进程注入等提权1. 前言2. at本地命令提权2.1. 适用范围2.2. 命令使用2.3. 操作步骤2.3.1. 模拟提权2.3.2. at配合msf提权2.3.2.1. 生成木马文件2.3.2.2. 设置监听2.3.2.3. 设置反弹2.3.2.4. 查看反弹效果3. sc本地命令提权3.1. 适用范围3.…

QT在线换源安装

Win11上Pytorch的安装并在Pycharm上调用PyTorch最新超详细 网上资源越来越多&#xff0c;关于PyTorch的安装教程各式各样&#xff0c;下面我将详细介绍在安装过程中的操作步骤。 经过上述流程图的介绍我们心中对安装过程有了一个大致的轮廓。下面我将对每一步进行细致的说明 步…

深度分析Palantir的投资价值,Palantir2023年将实现强劲反弹?

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 在本文中&#xff0c;猛兽财经将通过对Palantir的股票关键指标、商业模式、盈利能力、影响Palantir2023年股价的关键利好因素等方面&#xff0c;对Palantir进行全面、深度的分析。 Palantir股票的关键指标 自从Palantir(PL…