Linux系统编程学习--第4天文件属性和目录操作

本文详细介绍了Linux系统中的文件属性结构体`structstat`,以及相关库函数如stat、fstat、lstat的功能、参数和使用示例。还涵盖了文件类型判断、权限检查、目录操作(如mkdir、rmdir、getcwd、chdir等)和权限更改等内容。
摘要由CSDN通过智能技术生成

linux的理念一切皆文件。
文件属性结构体,这个结构体里面存储了文件的信息

struct stat {
	dev_t     st_dev; /*如果是设备,返回文件使用的设备号,否则为 0*/
	ino_t       st_ino; /* 索引节点号 */
	mode_t    st_mode; /* 文件类型 */
	nlink_t   st_nlink; /* 文件的硬连接数 */
	uid_t    st_uid; /* 所有者用户识别号*/
	gid_t   st_gid; /* 组识别号 */
	dev_t   st_rdev; /* 设备类型*/
	off_t   st_size; /* 文件大小,字节表示 */
	blksize_t    st_blksize; /*  系统每次按块Io操作时块的大小(一般是512或1024)*/
	blkcnt_t   st_blocks; /*块的索引号 */
	time_t    st_atime; /* 最后访问时间,如read*/
	time_t    st_mtime; /* 最后修改时间*/
	time_t    st_ctime; /* 创建时间 */
};

库函数
1、stat提供文件名字,获取文件对应属性。

函数原型:int stat(const char *path,struct stat *buf)
函数功能:根据文件路径path读取文件属性存储到buf结构体中
函数参数:path文件的路径,buf:存储文件属性的结构体
函数返回值:成功返回0,失败返回-1
函数头文件:#include <sys/types.h>
			#include <sys/stat.h>
			#include <unistd.h>

通过linux指令ls可以查看文件的属性
在这里插入图片描述
从左到右属性依次为
1:文件类型,linux文件类型一共有七种,普通文件类型(-),目录文件(d),块设备文件(b),字符设备©,套接字文件(s),管道文件§,链接文件(l).我们查看的文件类型是-普通文件
2:权限,拥有者、所属组、其它人的权限一共三组,rwx分别是读写执行
3:链接到inode的数目
4:拥有者
5:所属组
6:文件大小
7:文档最后修改时间:1月4日5点45
8:文件名1234

编程:利用函数读到文件属性,并打印文件大小

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int main(int argc,char* args[])
{
	struct stat ss={0};
	if(stat("./1234",&ss)==0)
	{
		printf("获取文件属性成功,文件名:%ld\n",ss.st_size);
	}	
}

在这里插入图片描述
2、fstat利用文件描述符获取文件属性,stat是利用文件路径获取的,这个是文件描述符,那么就需要open打开文件获取文件描述符

函数原型:int fstat(int fds,struct stat *buf)
函数功能:根据文件描述符读取文件属性存储到buf结构体中
函数参数:fds:文件描述符,buf:存储文件属性的结构体
函数返回值:成功返回0,失败返回-1
函数头文件:#include <sys/types.h>
			#include <sys/stat.h>
			#include <unistd.h>

编程:用fstat获取文件属性

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc,char* args[])
{
	//非缓冲区可追加读写方式打开文件
	int i=open("./1234",O_RDWR);
	if(i==-1)
	{
		printf("打开文件失败\n");
		return -1;
	}else
	{
		printf("打开文件成功\n");
	}
	struct stat ss={0};
	if(fstat(i,&ss)==0)
	{
		printf("获取文件属性成功,文件大小:%ld\n",ss.st_size);
	}
}

在这里插入图片描述
3、lstat返回文件信息
在这里插入图片描述
lstat和stat的区别是当你要访问的文件是个链接文件时,stat返回的是链接文件的信息,lstat返回的时链接文件所指向的文件。
4、判断文件的类型
我们获取存有文件信息的结构体stat之后,可以用结构体中的一项:mode_t st_mode; /* 文件类型 */,配合下面七个宏判断文件的类型。
宏:为真则是对应类型的文件

S_ISLNK(st_mode):是否是一个连接.
 S_ISREG(st_mode):是否是一个常规文件.
 S_ISDIR(st_mode):是否是一个目录
 S_ISCHR(st_mode):是否是一个字符设备.
 S_ISBLK(st_mode):是否是一个块设备
 S_ISFIFO(st_mode):是否 是一个FIFO文件.
 S_ISSOCK(st_mode):是否是一个SOCKET文件

编程,判断1234文件是否为常规文件

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc,char* args[])
{
	//非缓冲区可追加读写方式打开文件
	int i=open("./1234",O_RDWR);
	if(i==-1)
	{
		printf("打开文件失败\n");
		return -1;
	}else
	{
		printf("打开文件成功\n");
	}
	struct stat ss={0};
	if(fstat(i,&ss)==0)
	{
		printf("获取文件属性成功,文件大小:%ld\n",ss.st_size);
		if(S_ISREG(ss.st_mode))
		{
			printf("文件类型:普通文件\n");
		}
	}
}

在这里插入图片描述
5、access对文件权限的核查

函数原型: int access(const char *pathname, int mode);
函数功能:可检测当前用户(运行这个程序的用户)对某文件是否有某权限
函数参数:pathname:文件路径,mode:权限,有以下四种可并上|判断如果都通过则返回0,失败返回-1.
R_OK:测试读权限
W_OK:测试写权限
X_OK:测试执行权限
F_OK:测试文件是否存在
函数返回值:若所有欲查核的权限都通过了检查则返回0值,表示成功,只要有一权限被禁止则返回-1
函数头文件:#include <unistd.h>
注意:access检查的文件如果是属于普通用户下,只检测当前用的权限,如果要是属于root用户,那么他检测的是所有用户的权限

编程:判断1234是否存在,如果存在判断是否有读、写、执行的权限。

#include <stdio.h>
#include <unistd.h>
int main(int argc,char* args[])
{
	if(access("./1234",F_OK)==0)
	{
		printf("文件存在\n");
	}else
	{
		printf("文件不存在\n");
		return -1;
	}
	if(access("./1234",R_OK)==0)
	{
		printf("文件可读\n");
	}
	if(access("./1234",W_OK)==0)
	{
		printf("文件可写\n");
	}
	if(access("./1234",X_OK)==0)
	{
		printf("文件可执行\n");
	}
}

在这里插入图片描述

目录操作

1、mkdir创建目录

函数原型: int mkdir(const char *pathname, mode_t mode);
函数功能:创建目录
函数参数:pathname:文件路径,mode:权限给数字即可比如7的二进制为111,那么就是可读写执行,4的二进制为100,即为可读
函数返回值:成功返回0,错误返回-1
函数头文件: #include <sys/stat.h> 
			 #include <sys/types.h>

编程,创建一个可读可写且名为234的文件

#include <stdio.h>
#include <sys/stat.h> 
#include <sys/types.h>
int main(int argc,char* args[])
{
	if(mkdir("./234",0644)==0)//注意是三组的权限,拥有者、所属组、其他人的权限
	{
		printf("创建成功\n");
	}
}

在这里插入图片描述
2、rmdir删除目录

函数原型: int rmdir(const char *pathname);
函数功能:删除目录
函数参数:pathname:文件路径
函数返回值:成功返回0,错误返回-1
函数头文件: #include  <unistd.h>

编程:删除234目录

#include <stdio.h>
#include <unistd.h>
int main(int argc,char* args[])
{
	if(rmdir("./234")==0)
	{
		printf("删除成功\n");
	}
}

在这里插入图片描述
3、getcwd获取当前目录,相当于pwd命令

函数原型:  char *getcwd(char *buf, size_t size);
 char *get_current_dir_name(void);
 //char *getwd(char *buf);(最后一个不常用)
函数功能:获取当前目录
函数参数:buf:保存当前目录缓存区。size:buf最大为255字节
函数返回值:成功返回指向当前目录的指针,和部分值一样,错误返回NULL
函数头文件: #include  <unistd.h>

编程:获取当前目录

#include <stdio.h>
#include <unistd.h>
int main(int argc,char* args[])
{
	char buf[256]={0};
	if(getcwd(buf,255)!=NULL)
	{
		printf("当前目录:%s\n",buf);
	}
}

在这里插入图片描述
4、chdir改变当前目录,相当于cd命令(切换目录)

函数原型: int chdir(const char *path);
函数功能:修改当前目录,即切换目录,相当于 cd 命令
函数参数:path:文件路径
函数返回值:成功返回0,失败返回-1
函数头文件: #include  <unistd.h>

编程:返回上一层目录

#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main(int argc,char* args[])
{
	char buf[256]={0};
	if(getcwd(buf,255)!=NULL)
	{
		printf("切换之前目录:%s\n",buf);
	}
	if(chdir("..")==0)//.代表当前目录   ..代表上一层目录
	{
		printf("切换成功\n");
	}
	memset(buf,0,256);//清空buf
	if(getcwd(buf,255)!=NULL)
	{
		printf("切换之后目录:%s\n",buf);
	}
}

在这里插入图片描述
5、chmod更改权限

函数原型: int chmod(const char *path, mode_t mode);
函数功能:更改权限
函数参数:path:文件路径,mode:权限
函数返回值:成功返回0失败-1
函数头文件:#include <sys/types.h>
 			#include <sys/stat.h>

编程:更改1234文件的权限为0644

在这里插入图片描述
可以看到当前1234文件的权限为0664
运行代码

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
int main(int argc,char* args[])
{
	if(chmod("./1234",0644)==0)
	{
		printf("更改权限成功\n");
	}
}

在这里插入图片描述
6、opendir打开目录

函数原型:DIR *opendir(const char *name); 
函数功能:打开目录
函数参数:name:目录的路径
函数返回值:成功返回指向当前目录的指针,错误返回NULL
函数头文件:#include <sys/types.h>
			#include <dirent.h>

编程:打开一个目录

#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
int main(int argc,char* args[])
{
	DIR *ss=opendir("/home/xxx/Desktop/shell");
	if(ss!=NULL)
	{
		printf("打开目录成功\n");
	}
}

在这里插入图片描述

7、closedir关闭目录

函数原型: int closedir(DIR *dir);
函数功能:关闭目录
函数参数:opendir返回的指针
函数返回值:成功返回0,错误返回-1
函数头文件:#include <sys/types.h>
			#include <dirent.h>

编程:关闭打开的目录

#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
int main(int argc,char* args[])
{
	DIR *ss=opendir("/home/xxx/Desktop/shell");
	if(ss!=NULL)
	{
		printf("打开目录成功\n");
	}
	if(closedir(ss)==0)
	{
		printf("关闭目录成功\n");
	}
}

在这里插入图片描述
8、readdir读取目录信息
和文件一样目录也有自己存储信息的结构体

存储目录中的文件信息(文件名、扩展名等等)
#include <dirent.h>
struct dirent
{
   		long d_ino; /* inode number 索引节点号 */
   		off_t d_off; /* offset to this dirent 在目录文件中的偏移 */
   		unsigned short d_reclen; /* length of this d_name 文件名长 */
   		unsigned char d_type; /* the type of d_name 文件类型 */
   		char d_name [NAME_MAX+1]; /* file name (null-terminated) 文件名,最长255字符 */
}
d_tyep 有 8 种类型:
          
            (1)、 DT_BLK      This is a block device.           块设备
            (2)、 DT_CHR      This is a character device.       字符设备
            (3)、 DT_DIR       This is a directory.              目录
 
            (4)、 DT_FIFO     This is a named pipe (FIFO).      管道
            (5)、 DT_LNK      This is a symbolic link.          软链接
            (6)、 DT_REG      This is a regular file.           普通文件
            (7)、 DT_SOCK     This is a UNIX domain socket.     套接字
            (8)、 DT_UNKNOWN     The file type is unknown.         未知类型
函数原型: struct dirent *readdir(DIR *dir);
函数功能:读取目录信息
函数参数:打开目录后返回的文件指针
函数返回值:成功返回指向dirp的指针dirent,错误返回NULL
函数头文件:#include <sys/types.h>
			#include <dirent.h>

注意看这个结构体看上去只能存储一个文件的信息,那么怎么读取到目录中所有文件的信息呢?这个readdir方法第一次调用是读取在目录中偏移量为0,结构体里面存储的就是第一个文件的信息,当再次调用时这个方法就会读取偏移量为1的文件信息,循环调用循环读取,当读取不到时指针返回值为NULL。

编程:读取目录中所有文件的文件名

#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
int main(int argc,char* args[])
{
	DIR *ss=opendir("/home/xxx/Desktop/shell");
	if(ss!=NULL)
	{
		printf("打开目录成功\n");
	}
	struct dirent *dd=NULL;
	dd=readdir(ss);
	while(dd!=NULL)
	{
		printf("文件名:%s\n",dd->d_name);
		dd=readdir(ss);
	}
	
	if(closedir(ss)==0)
	{
		printf("关闭目录成功\n");
	}
}

在这里插入图片描述
9、rewinddir重新定位到目录文件的头部,就是把读取目录文件的偏移量归零

函数原型: void rewinddir(DIR *dir);
函数功能:重新定位到目录文件的头部
函数参数:打开目录后返回的文件指针
函数返回值:无
函数头文件:#include <sys/types.h>
			#include <dirent.h>

10、seekdir设置读取目录中文件的偏移量

函数原型: void seekdir(DIR *dir,off_t offset);
函数功能:设置参数dir 目录流目前的读取位置, 在调用readdir()时便从此新位置开始读取. 参数offset 代表距离目录文件开头的偏移量。
函数参数:打开目录后返回的文件指针,offset :代表距离目录文件开头的
偏移量
函数返回值:无
函数头文件:#include <sys/types.h>
			#include <dirent.h>
			注意:seekdir的偏移位置的变量是long int

上面读取文件时先读取1.c,然后再读取. 假如我不想读1.c就可以先偏移1个单位再读
11、telldir获取目录流的偏移量
在这里插入图片描述
这个函数我在测试时返回值很大,不知道是什么意思?如果有知道的朋友可以私我一下
在这里插入图片描述

  • 26
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值