4 文件属性和目录操作
一、目录操作
-- 目录操作主要的目的:让程序知道路径下有什么文件存在
-- 注:程序在哪里运行他的工作路径就在哪里 ,程序中所有的相对路径的文件就是基于工作路径来实现的
1、获取当前程序运行的工作路径
-- 函数头文件
- #include <unistd.h>
-- 函数原型
- char *getcwd(char *buf, size_t size);
-- 函数的作用:
- 获取程序运行所在的工作路径
-- 函数的参数:
- buf:用来存放获取到的工作路径的字符串的地址
- size:前面一个指针指向数组的大小
-- 函数的返回值:
- 成功返回 一个字符串的首地址 这个字符串为程序的工作路径
- 失败返回 NULL
#include <unistd.h>
#include <stdio.h>
char *getcwd(char *buf, size_t size);
int main()
{
//第一种:通过返回值
char *p = getcwd(NULL,0);
printf("%s\n",p);
if(p == NULL)
{
perror("getcwd");
}
/*
//第二种,通过参数
char buf[1024];
getcwd(buf,1024);
printf("%s\n",buf);
*/
}
注;有两种方法获取路径
2、更改程序的工作路径
-- 函数头文件
- #include <unistd.h>
-- 函数原型
- int chdir(const char *path);
-- 函数的作用:
- 更改程序的工作路径
-- 函数的参数:
- path:要进行跳转的工作路径
-- 函数返回值:
- 成功 0
- 失败 -1
#include <unistd.h>
#include <stdio.h>
int main(int argc, char const *argv[])
{
int d = chdir(argv[1]);
if(d == -1)
{
perror("chdir");
}
char *p = getcwd(NULL,0);
printf("%s\n",p);
return 0;
}
-- 下面是重点
- 目录操作类似于文件操作
- 按照下面的步骤即可实现目录操作
- 主要目的 可以获取目录下的文件名
3、打开目录流
-- 函数头文件
- #include <sys/types.h>
- #include <dirent.h>
-- 函数原型
- DIR *opendir(const char *name);
-- 函数的作用:
- 打开指定的目录并获取目录流指针
-- 函数的参数:
- name:填写要进行打开的目录路径
-- 函数的返回值:
- 成功返回 目录流指针
- 失败返回 NULL
#include <sys/types.h>
#include <dirent.h>
#include <stdio.h>
int main(int argc, char const *argv[])
{
DIR * p = opendir(argv[1]);
if(p == NULL)
{
perror("opendir");
}
printf("打开%s目录成功!\n",argv[1]);
return 0;
}
2、从目录流中读取出来一个文件
-- 函数头文件
- #include <dirent.h>
-- 函数原型
- struct dirent *readdir(DIR *dirp);
-- 函数的作用:
- 从目录流中读取出来一个文件
-- 函数的参数:
- DIR *dirp:opendir 的返回值 打开的目录流指针
-- 函数的返回值:
- 成功返回 读取到的文件
- 失败返回 NULL 读取到目录尾也返回 NULL
tip:节点号 “ls -i”可以看到
3、关闭目录流指针
-- 函数头文件
- #include <sys/types.h>
- #include <dirent.h>
-- 函数原型
- int closedir(DIR *dirp);
-- 函数的作用
- 关闭打开过的目录流指针
-- 函数的参数
- DIR *dirp:opendir 的返回值 目录流指针
-- 函数的返回值:
- 成功 0
- 失败 -1
4、通过函数创建出来一个文件夹
-- 函数头文件
- #include <sys/stat.h>
- #include <sys/types.h>
-- 函数原型
- int mkdir(const char *pathname, mode_t mode);
-- 函数的作用:
- 通过函数来创建出来一个文件夹
-- 函数的参数:
- pathname:要进行创建的文件名和路径
- mode:创建出来的文件夹权限 0777
-- 函数的返回值:
- 成功 0
- 失败 -1
#include <sys/stat.h>
#include <sys/types.h>
#include <stdio.h>
int main(int argc, char const *argv[])
{
int d = mkdir(argv[1], 0777);
if(d == -1)
{
perror("mkdir");
}
return 0;
}
4、删除空文件夹
-- 函数头文件
- #include <unistd.h>
-- 函数原型
- int rmdir(const char *pathname);
-- 函数原型
- 删除一个空文件夹
-- 函数的参数
- pathname:要进行删除的文件夹名称
-- 函数的返回值:
- 成功 0
- 失败 -1
注:只能删除空文件!!!
4、修改文件的权限
-- 函数头文件
- #include <sys/stat.h>
-- 函数原型 int chmod(const char *pathname, mode_t mode);
-- 函数的作用
- 修改文件的权限
-- 函数的参数
- pathname:要进行修改的文件名
- mode:权限
-- 函数的返回值:
- 成功 0
- 失败 -1
二、文件属性
-- 可以获取文件的详细信息
- 例如:文件的类型 文件的权限 文件的硬链接数 文件的大小 文件的创建时间 文件的修改时间 文件的最后操作时间
stat
-- 函数头文件
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <unistd.h>
-- 函数原型
- int stat(const char *pathname, struct stat *statbuf);
-- 函数的作用:
- 获取文件的详细信息
-- 函数的参数:
- pathname:要查看的文件名
- struct stat *statbuf:填写同数据类型的地址
-- 传出参数
- 将第一个参数的文件详细信息传出来
-- 函数的返回值:
- 成功返回 0
- 失败返回 -1
注:stat 函数如果去获取软链接文件的信息 实际获得的是源文件的信息
-- int lstat(const char *pathname, struct stat *statbuf);
- 该函数可以用来获取软链接文件的详细信息
-- int fstat(int fd, struct stat *statbuf);
- 该函数也可以获取文件的详细信息但是必须要先 通过 open 来打开文件
例1 :
仿写 find 指令 ./a.out 路径 文件名 or 后缀 -- 打印出来所有文件的绝对路径
/*
仿写 find 指令
./a.out 路径 文件名 or 后缀
打印出来所有文件的绝对路径
*/
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include <string.h>
void find_files(const char *a, const char *b) {
DIR *p = opendir(a);
if (p == NULL) {
perror("opendir");
return;
}
struct dirent *file;
char new_path[PATH_MAX]; // 存储当前文件的绝对路径
while ((file = readdir(p)) != NULL) {
if (strcmp(file->d_name, ".") == 0 || strcmp(file->d_name, "..") == 0) {
continue;
}
// 创建新的路径
snprintf(new_path, sizeof(new_path), "%s/%s", a, file->d_name);
if (strcmp(b, file->d_name) == 0) {
printf("%s\n", new_path);
}
// 如果是目录,递归搜索
if (file->d_type == DT_DIR) {
find_files(new_path, b);
}
}
closedir(p);
}
int main(int argc, char const *argv[]) {
if (argc < 3) {
printf("使用方法: %s 路径 文件名或后缀\n", argv[0]);
return -1;
}
find_files(argv[1], argv[2]);
return 0;
}
例2:
-- 实现仿写 ls -l
- 例如: ./a.out 文件名 显示该文件的详细信息
- ./a.out 显示当前路径下的所有文件的详细信息
- ./a.out 路径 显示该路径下的所有文件的详细信息
/*
实现仿写 ls -l
例如: ./a.out 文件名 显示该文件的详细信息
./a.out 显示当前路径下的所有文件的详细信息
./a.out 路径 显示该路径下的所有文件的详细信息
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <time.h>
#include <dirent.h>
#include <string.h>
#include <pwd.h>
#include <grp.h>
void get_type(int a);
void get_rwx(int a);
int main(int argc, char const *argv[]) {
char *path;
if (argc == 1) {
path = getcwd(NULL, 0);
if (path == NULL) {
perror("getcwd");
return -1;
}
} else {
path = (char *)argv[1];
}
DIR *dir = opendir(path);
if (dir == NULL) {
perror("opendir");
return -1;
}
struct dirent *entry;
struct stat f; // 用于存放文件状态
while ((entry = readdir(dir)) != NULL) {
char fullPath[1024];
snprintf(fullPath, sizeof(fullPath), "%s/%s", path, entry->d_name); // 生成完整路径
if (stat(fullPath, &f) == -1) {
perror("stat");
continue; // 跳过无法访问的文件
}
get_type(f.st_mode);
get_rwx(f.st_mode/64%8);
get_rwx(f.st_mode/8%8);
get_rwx(f.st_mode%8);
printf("%ld\t", f.st_nlink);
printf("%s\t", getpwuid(f.st_uid)->pw_name);
printf("%s\t", getgrgid(f.st_gid)->gr_name);
printf("%ld\t", f.st_size);
char timebuf[80];
struct tm *tm_info = localtime(&f.st_mtime);
strftime(timebuf, sizeof(timebuf), "%b %d %H:%M", tm_info);
printf(" %s\t", timebuf);
printf(" %s\n", entry->d_name);
}
closedir(dir);
if (argc == 1) {
free(path);
}
return 0;
}
void get_type(int a)
{
if(S_ISFIFO(a))
printf("p");
else if(S_ISBLK(a))
printf("b");
else if(S_ISCHR(a))
printf("c");
else if(S_ISDIR(a))
printf("d");
else if(S_ISLNK(a))
printf("l");
else if(S_ISREG(a))
printf("-");
else if(__S_ISTYPE((a), __S_IFSOCK))
printf("s");
}
void get_rwx(int a)
{
switch(a)
{
case 0:printf("---");break;
case 1:printf("--x");break;
case 2:printf("-w-");break;
case 3:printf("-wx");break;
case 4:printf("r--");break;
case 5:printf("r-x");break;
case 6:printf("rw-");break;
case 7:printf("rwx");break;
}
}