系统编程-文件属性和目录操作

4 文件属性和目录操作

一、目录操作

-- 目录操作主要的目的:让程序知道路径下有什么文件存在

-- 注:程序在哪里运行他的工作路径就在哪里 ,程序中所有的相对路径的文件就是基于工作路径来实现的

alt text

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);
    */
}

注;有两种方法获取路径

alt text

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;
}

alt text


-- 下面是重点

  • 目录操作类似于文件操作
  • 按照下面的步骤即可实现目录操作
  • 主要目的 可以获取目录下的文件名

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

alt text

tip:节点号 “ls -i”可以看到

alt text

alt text

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

alt text


注: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;
}
}

  • 14
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值