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获取目录流的偏移量
这个函数我在测试时返回值很大,不知道是什么意思?如果有知道的朋友可以私我一下