嵌入式Linux系统编程 — 3.7 文件目录与处理

目录

1 文件目录

1.1 文件目录简介

1.2 目录存储形式

2 创建和删除目录

2.1 mkdir创建目录

2.2 rmdir删除空目录

3 opendir打开、 readdir读取以及closedir关闭目录

3.1 打开文件 opendir

3.2 读取目录 readdir

3.3 重置目录起点rewinddir

3.4 关闭目录 closedir

3.4 示例程序 

4 进程的当前工作目录 

4.1 获取进程的当前工作目录getcwd

4.2 改变当前工作目录chdir()和 fchdir()

5 删除文件

5.1 unlink 函数删除文件

5.2 remove 函数删除文件

5 文件重命名renme


1 文件目录

1.1 文件目录简介

在Linux系统中,文件目录(也常称为文件夹)是一种特殊的文件,它用于组织和管理文件系统中的文件和子目录。目录本身也被视为文件,但是它们具有一些特殊的属性和操作方式,不同于普通文件。

在 Linux 系统下,会有一些专门的系统调用或 C 库函数用于对文件夹进行操作,譬如:打开、创建文件夹、删除文件夹、读取文件夹以及遍历文件夹中的文件等。

1.2 目录存储形式

目录在文件系统中的存储方式与常规文件类似,常规文件包括了 inode 节点以及文件内容数据存储块(block);但对于目录来说, 其存储形式则是由 inode 节点和目录块所构成,目录块当中记录了有哪些文件组织在这个目录下,记录它们的文件名以及对应的 inode 编号。其存储形式如下图所示:

目录块当中有多个目录项(或叫目录条目) ,每一个目录项(或目录条目) 都会对应到该目录下的某一个文件,目录项当中记录了该文件的文件名以及它的 inode 节点编号,所以通过目录的目录块便可以遍历找到该目录下的所有文件以及所对应的 inode 节点。

2 创建和删除目录

2.1 mkdir创建目录

mkdir 函数是C语言标准库中的一个函数,用于在文件系统中创建一个新的目录。这个函数的原型如下:

#include <sys/stat.h> 

int mkdir(const char *pathname, mode_t mode);
  • pathname指向一个以null结尾的字符串,指定要创建的目录的路径。
  • mode用于设置新目录的权限。这个值通常使用S_IRWXU(所有者读、写、执行权限) | S_IRWXG(组读、写、执行权限) | S_IRWXO(其他用户读、写、执行权限)的组合来定义。

下面是一个使用命令行参数来创建目录的示例程序:

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <errno.h>

int main(int argc, char *argv[]) 
{
    // 检查是否提供了目录名作为命令行参数
    if (argc != 2) {
        fprintf(stderr, "Usage: %s directory_name\n", argv[0]);
        return EXIT_FAILURE;
    }

    const char *dir = argv[1]; // 命令行参数作为目录名
    mode_t mode = S_IRWXU | S_IRWXG | S_IRWXO; // 所有者、组和其他用户都有读、写、执行权限

    if (mkdir(dir, mode) == -1) {
        if (errno == EEXIST) {
            printf("Directory '%s' already exists.\n", dir);
        } else {
            perror("mkdir failed"); // perror函数会打印错误信息
        }
        return errno;
    }

    printf("Directory '%s' created successfully\n", dir);
    return 0;
}

程序在运行时提供一个参数,即目录名。如果用户提供了正确的参数数量,程序将尝试创建一个具有指定权限的目录。如果目录创建成功,程序将打印一条成功消息。如果目录已经存在,程序将打印一条相应的消息。如果发生其他错误,perror 函数将打印错误信息。程序运行结果如下:

2.2 rmdir删除空目录

rmdir 函数是C语言标准库中用于删除空目录的函数。如果目录不为空,rmdir 函数将失败。以下是 rmdir 函数的原型:

#include <unistd.h>

int rmdir(const char *pathname);
  • pathname:指向一个以null结尾的字符串,指定要删除的目录的路径。

 下面是一个使用 main 函数和命令行参数来删除目录的示例程序:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

int main(int argc, char *argv[]) 
{
    // 检查是否提供了目录名作为命令行参数
    if (argc != 2) {
        fprintf(stderr, "Usage: %s directory_name\n", argv[0]);
        return EXIT_FAILURE;
    }

    const char *dir = argv[1]; // 命令行参数作为目录名

    if (rmdir(dir) == -1) {
        if (errno == ENOTEMPTY) {
            printf("Directory '%s' is not empty.\n", dir);
        } else {
            perror("rmdir failed"); // perror函数会打印错误信息
        }
        return errno;
    }

    printf("Directory '%s' removed successfully\n", dir);
    return 0;
}

程序在运行时提供一个参数,即要删除的目录名。如果提供了正确的参数数量,程序将尝试删除该目录。如果目录删除成功,程序将打印一条成功消息。如果目录不为空,程序将打印一条相应的消息。

3 opendir打开、 readdir读取以及closedir关闭目录

3.1 打开文件 opendir

opendir()函数用于打开一个目录,并返回指向该目录的句柄,供后续操作使用。 Opendir 是一个 C 库函数, opendir()函数原型如下所示:

#include <sys/types.h>
#include <dirent.h>

DIR *opendir(const char *name);
  • name: 指定需要打开的目录路径名,可以是绝对路径,也可以是相对路径。
  • 返回值: 成功将返回指向该目录的句柄,一个 DIR 指针(其实质是一个结构体指针),其作用类似于open函数返回的文件描述符fd,后续对该目录的操作需要使用该DIR指针变量;若调用失败,则返回NULL。

3.2 读取目录 readdir

readdir()用于读取目录,获取目录下所有文件的名称以及对应 inode 号。readdir()是一个 C 库函数(事实上 Linux 系统还提供了一个 readdir 系统调用),其函数原型如下所示:

#include <dirent.h>

struct dirent *readdir(DIR *dirp);

dirp: 目录句柄 DIR 指针。
返回值: 返回一个指向 struct dirent 结构体的指针, 该结构体表示 dirp 指向的目录流中的下一个目录条目。在到达目录流的末尾或发生错误时,它返回 NULL。

每调用一次 readdir(),就会从 drip 所指向的目录流中读取下一条目录项(目录条目),并返回 struct dirent结构体指针(struct dirent 结构体记录了文件的 inode 编号和文件名等信息)。

当使用 opendir()打开目录时,目录流将指向了目录列表的头部(0) ,使用 readdir()读取一条目录条目之后,目录流将会向后移动、指向下一个目录条目。这其实跟 open()类似, 当使用 open()打开文件的时候,文件位置偏移量默认指向了文件头部,当使用 read()或 write()进行读写时,文件偏移量会自动向后移动。

3.3 重置目录起点rewinddir

rewinddir()是 C 库函数,可将目录流重置为目录起点, 以便对 readdir()的下一次调用将从目录列表中的第一个文件开始。 rewinddir 函数原型如下所示:

#include <sys/types.h>
#include <dirent.h>

void rewinddir(DIR *dirp);
  • dirp: 目录句柄

3.4 关闭目录 closedir

closedir()函数用于关闭处于打开状态的目录,同时释放它所使用的资源,其函数原型如下所示:

#include <sys/types.h>
#include <dirent.h>

int closedir(DIR *dirp);

3.4 示例程序 

下面的示例程序接收命令行参数作为目录名,然后列出该目录下的所有文件和目录项:

#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <errno.h>

int main(int argc, char *argv[]) 
{
    // 检查是否提供了目录名作为命令行参数
    if (argc != 2) {
        fprintf(stderr, "Usage: %s directory_name\n", argv[0]);
        return EXIT_FAILURE;
    }

    const char *dir_name = argv[1]; // 命令行参数作为目录名
    DIR *dir_ptr = NULL;
    struct dirent *entry;

    // 打开目录以供读取
    dir_ptr = opendir(dir_name);
    if (dir_ptr == NULL) {
        perror("opendir failed"); // perror函数会打印错误信息
        return errno;
    }

    // 读取目录中的所有条目
    while ((entry = readdir(dir_ptr)) != NULL) {
        printf("%s\n", entry->d_name); // 打印文件或目录名
    }

    // 关闭目录流
    if (closedir(dir_ptr) == -1) {
        perror("closedir failed");
        return errno;
    }

    return 0;
}

在这个示例中,程序首先检查命令行参数的数量是否正确。如果正确,它将尝试打开指定的目录。如果目录成功打开,程序将使用 readdir 函数遍历目录中的所有条目,并打印每个条目的名称。最后,使用 closedir 函数关闭目录流。程序运行结果如下:

4 进程的当前工作目录 

4.1 获取进程的当前工作目录getcwd

getcwd 函数是 POSIX 标准定义的用于获取当前工作目录的完整路径的函数。以下是 getcwd 函数的原型:

#include <unistd.h> 

char *getcwd(char *buf, size_t size);
  • buf:指向一个字符数组的指针,用于存储当前工作目录的路径。如果为 NULLgetcwd 将分配一个足够大的缓冲区。
  • size:缓冲区的大小。

下面是使用 getcwd 函数的示例程序,该程序将打印当前工作目录的路径:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

int main(void) {
    char *buffer;
    size_t bufferSize = 1024;

    // 尝试获取当前工作目录
    buffer = getcwd(NULL, bufferSize); // 使用 NULL 让 getcwd 分配缓冲区
    if (buffer == NULL) {
        perror("getcwd failed"); // perror 函数会打印错误信息
        return errno;
    }

    // 打印当前工作目录
    printf("Current working directory: %s\n", buffer);

    // 释放 getcwd 分配的缓冲区
    free(buffer);

    return 0;
}

getcwd 被用来获取当前工作目录的路径,并将结果存储在 buffer 中。如果 getcwd 成功,程序将打印当前工作目录的路径。如果失败,perror 函数将打印错误信息。最后,如果 getcwd 分配了缓冲区,程序将使用 free 函数释放它。运行结果如下:

4.2 改变当前工作目录chdir()和 fchdir()

chdir()fchdir() 是两个用于更改当前工作目录的函数,两个函数的原型如下:

#include <unistd.h> 

int chdir(const char *path);
  • path:指向以null结尾的字符串的指针,指定要切换到的目录的路径。
#include <unistd.h> 

int fchdir(int fd);
  • fd:文件描述符,指向一个目录的文件描述符。

5 删除文件

5.1 unlink 函数删除文件

unlink 函数用于删除文件的函数,以下是 unlink 函数的原型:

#include <unistd.h> 

int unlink(const char *pathname);
  • pathname:指向以null结尾的字符串的指针,指定要删除的文件的路径。

下面是一个使用 unlink 函数删除文件的示例程序,该程序接收命令行参数作为要删除的文件名:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

int main(int argc, char *argv[]) {
    // 检查是否提供了文件名作为命令行参数
    if (argc != 2) {
        fprintf(stderr, "Usage: %s filename\n", argv[0]);
        return EXIT_FAILURE;
    }

    const char *filename = argv[1]; // 命令行参数作为文件名

    // 尝试删除文件
    if (unlink(filename) == -1) {
        perror("unlink failed"); // perror 函数会打印错误信息
        return errno;
    }

    printf("File '%s' has been successfully deleted\n", filename);
    return 0;
}

程序首先检查命令行参数的数量是否正确。如果正确,它将尝试删除指定的文件。如果文件删除成功,程序将打印一条成功消息。如果删除失败,perror 函数将打印错误信息。运行结果如下,从测试结果可看到,只能删除文件,不能删除文件夹

5.2 remove 函数删除文件

remove 函数是C标准库中的一个函数,它可以删除文件或空目录。与unlink不同,remove可以删除空目录,但不能删除非空目录。以下是remove函数的原型:

#include <stdio.h> 

int remove(const char *filename);
  • filename:指向以null结尾的字符串的指针,指定要删除的文件或目录的路径。

示例程序将5.1中的unlink变为remove ​​​​​​​,运行结果如下,从运行结果可以看到,remove可以删除目录。

5 文件重命名renme

rename 函数用于重命名文件或目录。以下是 rename 函数的原型:

#include <stdio.h> 

int rename(const char *oldpath, const char *newpath);
  • oldpath:指向以null结尾的字符串的指针,指定要重命名的文件或目录的当前名称。
  • newpath:指向以null结尾的字符串的指针,指定新的名称。

下面是 rename 函数重命名文件的示例程序,程序接收两个命令行参数:oldpathnewpath: 

程序首先检查命令行参数的数量是否正确。如果正确,它将尝试将文件或目录从 oldpath 重命名为 newpath。如果重命名成功,程序将打印一条成功消息。如果重命名失败,perror 函数将打印错误信息。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/748000.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于DeepNLP AI Store真人点评和ShowCase分享社区-AI for Image Generator

来源 quora 社区: https://deepnlpaistore.quora.com/ github: https://rockingdingo.github.io/deepnlp/store/image_generator 内容 DeepNLP AI Store 网址&#xff1a;http://www.deepnlp.org/store/image-generator 网站针对图像生成类别 Image Generator下多个AI工具如 …

第 28 篇 : SSH秘钥登录

1 生成秘钥 ssh-keygen -t rsa ls -a ./.ssh/一直回车就行了 2. 修改配置 vi /etc/ssh/sshd_config放开注释 公钥的位置修改 关闭密码登录 PubkeyAuthentication yes AuthorizedKeysFile .ssh/id_rsa.pub PasswordAuthentication no3. 下载id_rsa私钥, 自行解决 注意…

Websocket在Java中的实践——自动注册端点

在《Websocket在Java中的实践——握手拦截器》中我们使用握手拦截器实现了路径解析的工作。这个过程略显复杂&#xff0c;因为路径解析这样比较底层的工作应该由框架来解决&#xff0c;而不应该交由开发者来做。本文介绍的自动注册端点的功能就可以很优雅的解决这个问题。 依赖…

GNU、Unix、Linux、Makefile、GCC、GDB、GPL、CentOS 7、Ubuntu之间的关系

全文总结 早期&#xff0c;Unix系统作为一类强大的操作系统&#xff0c;在计算领域奠定了基础。然而&#xff0c;出于对软件自由的追求&#xff0c;Richard Stallman在1983年发起了GNU项目&#xff0c;旨在创建一个完全自由的、与Unix兼容的操作系统。GNU项目不仅倡议软件自由…

初创企业合规管理中的企业合规义务边界问题

在初创企业的迅猛发展过程中&#xff0c;合规管理是确保公司可持续成长和避免潜在风险的关键因素。而在合规管理中&#xff0c;界定企业边界尤为重要&#xff0c;它关系到企业如何合理规划业务范围、管理内部外部关系以及维护企业形象和法律责任的清晰。 一、初创企业面临的合…

ubuntu 18 虚拟机安装(3)安装mysql

ubuntu 18 虚拟机安装&#xff08;3&#xff09;安装mysql 参考 https://cloud.tencent.com/developer/article/1700780 技术分享 | MySQL 设置管理员密码无法生效一例 https://cloud.tencent.com/developer/article/2014384 在Ubuntu18.04上安装MySQL &#xff5c; 超级详细…

flink-触发器Trigger和移除器Evictor

Trigger 触发器 触发器作用&#xff1a;控制窗口什么时候除法计算。即执行窗口函数&#xff1b;基于WindowStream调用trigger&#xff08;&#xff09;方法&#xff0c;传入自定义触发器&#xff08;trigger&#xff09;&#xff1b; 每一个窗口分配器&#xff08;windowAssi…

如何以智能方式安装 Python

Python易于使用&#xff0c;对初学者友好&#xff0c;功能强大&#xff0c;几乎可以为任何应用程序创建强大的软件。 但与任何其他软件一样&#xff0c;Python 的设置和管理可能很复杂。 在本文中&#xff0c;我们将介绍如何正确设置 Python。 您将学习如何选择合适的版本、…

JavaScript中常用数据类型做布尔值(Boolean)转换

一、前言 二、示例 1、String转Boolean 2、Number转Boolean 3、NaN、Null、undefined 转Boolean 4、Object转Boolean 5、Array转Boolean 6、Symbol转Boolean 三、总结 四、思考 一、前言 JavaScript中&#xff0c;经常需要对一些值进行boolean判断&#xff0c;根据判…

three.js 第六节 - 纹理以及贴图【.hdr文件(hdr贴图)】- 色彩空间

素材 这是素材 更多素材、案例、项目 好几个G一共&#xff0c;加我q178373168&#xff0c;60大洋拿走 源码 源码 // ts-nocheck // 引入three.js import * as THREE from three // 导入轨道控制器 import { OrbitControls } from three/examples/jsm/controls/OrbitControls…

【考研数学】李林《880》25版主要变化汇总

25版李林880拿到手后对比&#xff0c;发现和24几乎没有太大差别&#xff08;高数前两章20多道题目增删&#xff09;&#xff0c;然后24又和23版本一模一样 所以有24版本or23版本的880都可以&#xff0c;不用一定追求25年的&#xff01; 880算是比较经典的习题了&#xff0c;搭…

UE引擎实现ShadowMap、体积光(C++)

前言 整体上参考了YivanLee大佬的这两篇文&#xff1a; 虚幻4渲染编程&#xff08;灯光篇&#xff09;【第一卷&#xff1a;各种ShadowMap】 虚幻4渲染编程&#xff08;灯光篇&#xff09;【第二卷&#xff1a;体积光】 正文 1、ShadowMap &#xff08;1&#xff09;创建工…

上下文管理器在Python中的妙用

更多Python学习内容&#xff1a;ipengtao.com Python上下文管理器是一个非常强大的工具&#xff0c;它能够帮助开发者在特定代码块前后自动执行特定的操作&#xff0c;常用于资源管理&#xff0c;如文件操作、数据库连接和锁定等。本文将详细介绍Python上下文管理器的概念、使用…

django学习入门系列之第三点《案例 商品推荐部分》

文章目录 划分区域搭建骨架完整代码小结往期回顾 划分区域 搭建骨架 /*商品图片&#xff0c;父级设置*/ .slider .sd-img{display: block;width: 1226px;height: 460px; }<!-- 商品推荐部分 --> <!--搭建出一个骨架--> <div class"slider"><di…

云计算基础技术

云计算基础技术概览 计算类产品主要提供算力&#xff0c;支持业务运行&#xff0c;例如网站、办公软件、数据分析等计算能力&#xff0c;目前典型的产品主要是虚拟化和容器&#xff0c;在公有云上的云主机本质也是虚拟机。网络类产品主要满足资源的网络连通性和隔离&#xff0c…

鸿蒙NEXT开发:工具常用命令—install

安装三方库。 命令格式 ohpm install [options] [[<group>/]<pkg>[<version> | tag:<tag>]] ... ohpm install [options] <folder> ohpm install [options] <har file> alias: i 说明 group&#xff1a;三方库的命名空间&#xff0c;可…

告别数据线!轻松实现iOS和安卓设备间的文件共享

用 AirDroid 的附近传输功能&#xff0c;完全免费&#xff0c;几十个G的文件也可以相互传输。不限制iPhone和iPad数量&#xff0c;多个设备同时登录也不会强迫下线。 当你要在苹果手机和安卓手机之间传输文件&#xff0c;请将AirDroid安装到两台手机上&#xff0c;然后登录同一…

Open3D(C++) 删除点云中重复的点

目录 一、算法原理1、重叠点2、主要函数二、代码实现三、结果展示本文由CSDN点云侠原创,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫与GPT。 一、算法原理 1、重叠点 原始点云克隆一份   构造重叠区域   合并点云获得重叠点 2、主要…

【Mysql】多表、外键约束

多表 1.1 多表简述 实际开发中&#xff0c;一个项目通常需要很多张表才能完成。 例如一个商城项目的数据库,需要有很多张表&#xff1a;用户表、分类表、商品表、订单表… 1.2 单表的缺点 1.2.1 数据准备 创建一个数据库 db3 CREATE DATABASE db3 CHARACTER SET utf8;数据库…

Kompas AI数据分析与预测功能对比

一、引言 在现代商业环境中&#xff0c;数据分析与预测是企业制定战略决策的关键工具。通过对大量数据的分析&#xff0c;企业能够识别趋势、预测未来变化&#xff0c;并做出更为明智的决策。本文将对比Kompas AI与其他主要AI产品在数据分析与预测方面的能力&#xff0c;展示K…