1.15 目录操作函数
mkdir 函数
/*
#include <sys/stat.h>
#include <sys/types.h>
int mkdir(const char *pathname, mode_t mode);
作用:创建一个目录
参数:pathname 创建一个目录的路径
mode 权限(目录的权限和文件的权限有什么不同?)
目录的权限是包括可查看,可删除,可向目录当中写入文件吗?
返回值:
成功返回0,失败返回-1
*/
#include <sys/stat.h>
#include <sys/types.h>
#include<stdio.h>
int main(void){
int ret = mkdir("kk",0777);
if(ret == -1){
perror("mkdir");
return -1;
}
printf("make dirtionary.");
return 0;
}
rename 函数
#include <stdio.h>
// int rename(const char *oldpath, const char *newpath);
int main(void){
int ret = rename("kk","kkk");
if(ret == -1){
perror("rename");
return -1;
}
printf("rename success.");
return 0;
}
getcwd 函数
/*
#include <unistd.h>
int chdir(const char *path);
修改进程的工作目录
比如在 /home/tree/下启动了一个进程a.out, 进程的工作目录
path :修改该进程的工作目录到 path
#include <unistd.h>
char *getcwd(char *buf, size_t size);
作用:获取当前的工作目录
参数:
-buf 存储路径,指向的是一个数组(传出参数)
-size:数组的大小
相当于递给别人一张纸条,让别人写下当前目录的名字。
返回值:
返回指向的一个快内存,这个数据就是传入的第一个参数。
*/
#include<unistd.h>
#include<stdio.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<sys/types.h>
int main(void){
//获取当前的工作目录
char buf[128];
getcwd(buf,sizeof(buf));
printf("当前的工作目录是:%s",buf);
//改变当前的工作目录
int ret = chdir("/home/three/.vscode-server/.vscode/kkk");
if(ret == -1){
perror("chdir");
return -1;
}
//创建一个文件
int fd = open("chdir.txt",O_CREAT | O_RDWR,0664);
if(fd == -1){
perror("open");
return -1;
}
//文件创建完成后记得关掉文件指针
close(fd);
//再次获取当前的工作目录
char buf1[128];
getcwd(buf1,sizeof(buf1));
printf("当前的工作目录是:%s",buf1);
return 0;
}
rmdir 删除目录,前提是目录为空
1.16 目录遍历函数
#include <sys/types.h>
#include <dirent.h>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int getFileNumber(const char*path);
// //打开一个目录的函数
// #include <sys/types.h>
// #include <dirent.h>
// DIR *opendir(const char *name);
// //作用:打开一个目录
// 参数:
// //-name :要打开的目录的名字
// 返回值:DIR* 理解为一个目录流
// 失败返回一个null
// //获取目录的信息
// #include <dirent.h>
// struct dirent *readdir(DIR *dirp);
// 参数:
// // -DTR opendir 的返回值
// 返回值:
// // struct dirent :存放第一个返回的目录的信息。
// 如果读取到文件的末尾(目录中包含的文件)或者读取失败,返回null
// (有点类似于数据库当中的文件)
// 关闭目录
// #include <sys/types.h>
// #include <dirent.h>
// int closedir(DIR *dirp);
//读取某个目录下普通文件的个数
int main(int argc,char* argv[]){
if(argc < 2){
printf("%s : path",argv[0]);
return -1;
}
int num = getFileNumber(argv[1]);
printf("普通文件的个数为: %d\n",num);
return 0;
}
//用于获取目录下所有普通文件的个数,返回值为当前目录下文件的个数
int getFileNumber(const char*path){
//1.打开目录
DIR* dir = opendir(path);
if(dir == NULL){
perror("opendir");
//return -1;
exit(0);
}
//获取目录文件信息,如果是目录需要继续打开目录,如果是文件,需要继续打开文件。
// struct dirent* ptr = readdir(dir);
struct dirent* ptr;
//记录普通文件的个数
int total = 0;
while((ptr = readdir(dir)) != NULL){
//获取名称,如果是当前文件或者是上一级文件要忽略掉
char* dname = ptr->d_name;
//忽略掉 . 和 ..
if((strcmp(dname,".") == 0) || (strcmp(dname,"..") == 0))
continue;
//判断是普通文件还是目录
if(ptr->d_type == DT_DIR){
//确认是目录,需要递归调用
char newpath[256];//需要通过拼接来得到下一个要读取的目录的绝对路径名称
sprintf(newpath,"%s/%s",path,dname);
total += getFileNumber(newpath);
}
if(ptr->d_type == DT_REG){
total++;
}
}
closedir(dir);
return total;
}
测试结果:
dup 函数
测试程序:
/*
#include <unistd.h>
int dup(int oldfd);
作用:拷贝一个新的文件描述符,新的文件描述符和旧的文件描述符一样,指向同一个旧的文件
新的文件描述符是从原来空闲的文件描述符当中找一个最小的。
*/
#include<sys/types.h>
#include<unistd.h>
#include<stdio.h>
#include<string.h>
#include<sys/stat.h>
#include<fcntl.h>
int main(void){
int fd = open("c.txt",O_RDWR | O_CREAT,0664);
if(fd == -1){
perror("open");
return -1;
}
int fd1 = dup(fd);
if(fd1 == -1){
perror("dup");
return -1;
}
char *str = "hello, dup";
int len = write(fd1,str,strlen(str));
if(len == -1){
perror("write");
return -1;
}
printf("fd:%d,fd2:%d.",fd,fd1);
return 0;
}
运行结果:
dup2.c
/*
#include <unistd.h>
int dup2(int oldfd, int newfd);
作用:重定向新的文件作用符:
如果oldfd 和 newfd 指向的是同一个文件就什么都不做。
如果 newfd 指向的是另外一个文件调用改函数后,和 oldfd 一起指向原来 oldfd 所指向的文件。
原来的 newfd 和 newfd 所指向的文件做close
oldfd 必须是一个有效的文件描述符
*/
#include<sys/types.h>
#include<unistd.h>
#include<stdio.h>
#include<string.h>
#include<sys/stat.h>
#include<fcntl.h>
int main(void){
int fd = open("b1.txt",O_RDWR | O_CREAT,0664);
if(fd == -1){
perror("open");
return -1;
}
int fd1 = open("b2.txt",O_RDWR | O_CREAT,0664);
if(fd1 == -1){
perror("open");
return -1;
}
printf("fd:%d ,fd1:%d\n",fd,fd1);
int fd2 = dup2(fd,fd1);
if(fd1 == -1){
perror("dup2");
return -1;
}
//通过 fd1 去写数据,实际操作的是b1.txt,而不是b2.txt
char*str = "hello, dup2";
int len = write(fd1,str,strlen(str));
if(len == -1){
perror("dup2");
return -1;
}
printf("fd:%d, fd1:%d,fd2:%d",fd,fd1,fd2);
close(fd);
close(fd1);
return 0;
}
运行结果
/*
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... );
参数:
fd:表示需要操作的文件描述符
cmd:表示对文件描述符进行如何操作
- F_DUPFD :复制文件描述符,复制的是第一个fd所指向的文件的描述符,返回新的文件描述符
Duplicate the file descriptor fd using the lowest-numbered available file descriptor greater than or equal to arg. This
is different from dup2(2), which uses exactly the file descriptor specified.
On success, the new file descriptor is returned.
- F_GETFL:获取指定的文件描述符文件状态flag
这个flag 与用open 函数创建一个文件的时候所指定的flag是一致的。
-F_SETFL :设置文件描述符的状态flag
必选项:O_RDONLY,O_WRONLY,O_RDWR 必选项不可修改
可选项:NONBLOK,O_APPEND
NONBLOK:阻塞和非阻塞
O_APPEND :表示可以追加数据
阻塞和非阻塞:描述的是函数的调用的行为
阻塞,在函数调用得到返回值之前,当前的进程或者线程会被挂起
*/
#include <unistd.h>
#include <fcntl.h>
#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include<string.h>
int main(void){
// 1.复制文件描述符
// int fd = open("aaa.txt",O_RDONLY);
// int ret = fcntl(fd,F_DUPFD);
//2.查看和修改文件状态
// int fd = open("cc.txt",O_RDONLY);
//open 所传递的文件状态是不可修改的项
int fd = open("cc.txt",O_RDWR);
if(fd == -1){
perror("open");
return -1;
}
//获取原来的文件状态,防止直接传入文件参数被覆盖掉
int flag = fcntl(fd,F_GETFL);
if(flag == -1){
perror("fcntl");
return -1;
}
flag |= O_APPEND;
int ret = fcntl(fd,F_SETFL,flag);
if(ret == -1){
perror("fcntl");
return -1;
}
char*str = "nihao";
write(fd,str,strlen(str));
close(fd);
return 0;
}