Linux下的系统编程——文件与目录操作(六)

前言:

在Linux系统中,文件和目录的操作非常灵活。用户可以通过命令行或者图形界面来进行操作。下面是Linux文件和目录操作的一些常见操作:

目录

一、文件系统

1.inode

2.dentry 

 二、文件操作

1.stat/lstat:

2.link/unlink:

  3.隐式回收。

4.readlink 

5.rename

三、目录操作

1.文件目录权限

 2.目录操作函数:

(1)opendir:

(2)closedir:

(3)readdir:

(4)rewinddir

(5)telldir/seekdir 

 3.递归遍历目录

 四、重定向:

(1)dup :

 (2)dup2:

 五、fcntl实现dup描述符


一、文件系统

1.inode

        其本质为结构体,存储文件的属性信息。如:权限、类型、大小、时间、用户、盘块位置……也叫作文件属性管理结构,大多数的inode,都存储在磁盘上。
        少量常用、近期使用的inode会被缓存到内存中。,

2.dentry 

        目录项,其本质依然是结构体,重要成员变量有两个{文件名,inode,...},而文件内容(data)保存在磁盘盘块中。

 二、文件操作

1.stat/lstat:

stat/lstat 函数:

    int stat(const char *path, struct stat *buf);

    参数:
        path: 文件路径

        buf:(传出参数) 存放文件属性。

    返回值:

        成功: 0

        失败: -1 errno

    获取文件大小: buf.st_size


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

int main(int argc,char *argv[])
{

	struct stat sbuf;

	int ret = stat(argv[1],&sbuf);
	if(ret == -1){
		perror("stat error");
		exit(1);
	}
	printf("file size:%ld\n",sbuf.st_size);

	return 0;
}

  获取文件类型: buf.st_mode

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

int main(int argc,char *argv[])
{

	struct stat sb;

	int ret = stat(argv[1],&sb);
	if(ret == -1){
		perror("stat error");
		exit(1);
	}
	
	//printf("file size:%ld\n",sbuf.st_size);
	
	if(S_ISREG(sb.st_mode)){
		printf("It is a regular\n");
	}else if(S_ISDIR(sb.st_mode)){
		printf("It is a dir\n");
	}else if(S_ISFIFO(sb.st_mode)){
		printf("It is a pipe\n");
	}else if(S_ISLNK(sb.st_mode)){
		printf("It is a sym link\n");
	}
	
	return 0;
}

    获取文件权限: buf.st_mode

    符号穿透:stat会。lstat不会。

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

int main(int argc,char *argv[])
{

	struct stat sb;

	int ret = lstat(argv[1],&sb);
	if(ret == -1){
		perror("stat error");
		exit(1);
	}
	
	//printf("file size:%ld\n",sbuf.st_size);
	
	if(S_ISREG(sb.st_mode)){
		printf("It is a regular\n");
	}else if(S_ISDIR(sb.st_mode)){
		printf("It is a dir\n");
	}else if(S_ISFIFO(sb.st_mode)){
		printf("It is a pipe\n");
	}else if(S_ISLNK(sb.st_mode)){
		printf("It is a sym link\n");
	}
	
	return 0;
}

 

文件权限位图:

2.link/unlink:

link 函数,可以为已经存在的文件创建目录项(硬链接)

mv命令既是修改了目录项,而并不修改文件本身。↓
 

unlink:删除一个目录的文件项

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


int main(int argc,char *argv[])
{

	link(argv[1],argv[2]);

	unlink(argv[1]);
	
	return 0;
}

  3.隐式回收。

        当进程结束运行时,所有该进程打开的文件会被关闭,申请的内存空间会被释放。系统的这一特性称之为隐式回收系统资源。

4.readlink 

读取符号链接文件本身内容,得到链接所指向的文件名。
ssiz...t readlink(const char*path, char*buf, size_t bufsiz);

        成功:返回实际读到的字节数;

        失败:-1设置errno为相应值。

5.rename


重命名一个文件。
int rename(const char*oldpath, const char*newpath);

        成功: 0;

        失败: -1设置errno.为相应值。

和实现前面的myMv效果相同

三、目录操作

1.文件目录权限

注意:

        目录文件也是“文件”。其文件内容是该目录下所有子文件的目录项dentry。可以尝试用vim打开一个目录。

目录设置黏住位:

        若有w权限,创建不变,删除、修改只能由root、目录所有者、文件所有者操作。

用vi查看目录:  vi  目录        查看到的是:目录项

 *2.目录操作函数:

(1)opendir:

        根据传入的目录名打开一个目录(库函数)

        语法:DIR *opendir(const char *name);

        成功返回指向该目录结构体指针

        失败返回NULL

(2)closedir:

        关闭打开目录

        语法:int closedir(DIR*dirp); 

        成功:0;

        失败: -1设置errno为相应值。

(3)readdir:

        读取目录(库函数)

        语法:struct dirent*readdir(DIR*dirp);

        成功返回目录项结构体指针;

        失败返回NULL设置errno为相应值

需注意返回值,读取数据结束时也返回NULL值,所以应借助errno.进
步加以区分

 


	struct dirent *readdir(DIR * dp);

		struct dirent {

			inode
			char dname[256];

		};

(4)rewinddir

        回卷目录读写位置至起始。,
        语法:void rewinddir(DIR*dirp);返回值:无。

(5)telldir/seekdir 

        获取目录读写位置,
        语法:long telldir(DlR *dirp);

        成功:与dirn.相关的目录当前读写位置。

        失败-1,设置errno.

        修改目录读写位置
        void seekdir(DIR*dirp, long loc);

        返回值:无,

        参数loc一般由telldir函数的返回值来决定。

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

int main(int argc,char *argv[])
{
	DIR * dp;
	struct dirent *sdp;

	dp = opendir(argv[1]);
	if(dp == NULL){
		perror("opendir error");
		exit(1);
	}
	while((sdp = readdir(dp)) != NULL){
		printf("%s\n",sdp->d_name);
	}
	printf("\n");

	closedir(dp);

	return 0;
}

 *3.递归遍历目录

查询指定目录,递归列出目录中文件,同时显示文件大小

递归遍历目录:ls-R.c

    1. 判断命令行参数,获取用户要查询的目录名。    int argc, char *argv[1]

        argc == 1  --> ./

    2. 判断用户指定的是否是目录。 stat  S_ISDIR(); --> 封装函数 isFile() {   }

    3. 读目录:

 read_dir() { 

        opendir(dir)

        while (readdir()){

            普通文件,直接打印

            目录:
                拼接目录访问绝对路径。sprintf(path, "%s/%s", dir, d_name) 

                递归调用自己。--》 opendir(path) readdir closedir
        }

        closedir()

 }
 read_dir() --> isFile() ---> read_dir()

代码预览:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <dirent.h>
#include <pthread.h>

void isFile(char *name);

// 打开目录读取,处理目录
void read_dir(char *dir, void (*func)(char *))
{
    char path[259];
    DIR *dp;
    struct dirent *sdp;

    dp = opendir(dir);
    if (dp == NULL) {
        perror("opendir error");
        return;
    }
    // 读取目录项
    while((sdp = readdir(dp)) != NULL) {
        if (strcmp(sdp->d_name, ".") == 0 || strcmp(sdp->d_name, "..") == 0) {
            continue;
        }
        //fprintf();
        // 目录项本身不可访问, 拼接. 目录/目录项
        sprintf(path, "%s/%s", dir, sdp->d_name);

        // 判断文件类型,目录递归进入,文件显示名字/大小
        //isFile(path);    
        (*func)(path);
    }

    closedir(dp);

    return ;
}

void isFile(char *name)

    int ret = 0;
    struct stat sb;

    // 获取文件属性, 判断文件类型
    ret = stat(name, &sb);
    if (ret == -1) {
        perror("stat error");
        return ;
    }
    // 是目录文件
    if (S_ISDIR(sb.st_mode)) {
        read_dir(name, isFile);
    }
    // 是普通文件, 显示名字/大小
    printf("%10s\t\t%ld\n", name, sb.st_size);

    return;
}


int main(int argc, char *argv[])
{
    // 判断命令行参数
    if (argc == 1) {
        isFile(".");
    } else {
        isFile(argv[1]);
    }

	return 0;
}

 四、重定向:

(1)dup :

  int dup(int oldfd);        文件描述符复制。

        oldfd:  已有文件描述符

        返回:新文件描述符。

#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>

int main(int argc,char *argv[])
{
	int fd = open(argv[1],O_RDONLY);012 ----3
	
	int newfd = dup(fd);	//4

	printf("newfd = %d\n",newfd);

	return 0;
}

 *(2)dup2:

 int dup2(int oldfd, int newfd); 文件描述符复制。重定向。

#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>

int main(int argc,char *argv[])
{
	int fd1 = open(argv[1],O_RDWR);

	int fd2 = open(argv[2],O_RDWR);

	int fdret = dup2(fd1,fd2);
	printf("fdret = %d\n",fdret);

	int ret = write(fd2,"-----1234567-----",7);
	printf("ret = %d\n",ret);

	dup2(fd1,STDOUT_FILENO);
	printf("********--------------------********\n");

	return 0;
}

 五、fcntl实现dup描述符

fcntl 函数实现 dup:

    int fcntl(int fd, int cmd, ....)

    cmd: F_DUPFD

    参3:  被占用的,返回最小可用的。

        未被占用的, 返回=该值的文件描述符。

#include<stdio.h>
#include<fcntl.h>

int main(int argc,char *argv[])
{

	int fd1 = open(argv[1],O_RDWR);

	printf("fd1 = %d\n",fd1);

	int newfd = fcntl(fd1,F_DUPFD,0);//0被占用,fcntl使用文件描述符表中的最小文件描述符返回(4)
	printf("newfd = %d\n",newfd);

    int newfd2 = fcntl(fd1,F_DUPFD,7);//7 未被占用,返回>=7的文件描述符
	printf("newfd2 = %d\n",newfd2);

	return 0;
	
}

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

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

相关文章

运行命令出现错误 /bin/bash^M: bad interpreter: No such file or directory

在系统上运行一个 Linux 的命令的时候出现下面的错误信息&#xff1a; -bash: ./build.sh: /bin/bash^M: bad interpreter: No such file or directory 这个是在 Windows 作为 WSL 的时候出的错误。 原因和解决 出现问题的原因在于脚本在 Windows 中使用的回车换行和 Linux …

LLM学习笔记(1)

学习链接 ChatGPT Prompt Engineering for Developers - DeepLearning.AI 一、prompt engineering for developer 1、原则 prompting principles and iterative pattern 2、用于summarize 环境与helper functions import openai import osfrom dotenv import load_dotenv…

基于Kohonen网络的聚类算法

1.案例背景 1.1 Kohonen网络 Kohonen网络是自组织竞争型神经网络的一种,该网络为无监督学习网络,能够识别环境特征并自动聚类。Kohonen神经网络是芬兰赫尔辛基大学教授Teuvo Kohonen 提出的,该网络通过自组织特征映射调整网络权值,使神经网络收敛于一种表示形态。在这一形态中…

【LeetCode】1654:到家的最少跳跃次数的解题思路 关于力扣无法return的BUG的讨论

文章目录 一、题目二、题解与代码三、神奇的BUG3.1 无法执行的 return 和 break 语句3.2 通过另一个 break 解决 一、题目 有一只跳蚤的家在数轴上的位置 x 处。请你帮助它从位置 0 出发&#xff0c;到达它的家。 跳蚤跳跃的规则如下&#xff1a; 它可以 往前 跳恰好 a 个位…

Maven入门教程(三):Maven语法

视频教程&#xff1a;Maven保姆级教程 Maven入门教程(一)&#xff1a;安装Maven环境 Maven入门教程(二)&#xff1a;idea/Eclipse使用Maven Maven入门教程(三)&#xff1a;Maven语法 Maven入门教程(四)&#xff1a;Nexus私服 Maven入门教程(五)&#xff1a;自定义脚手架 6.Mav…

spring高级源码50讲-37-42(springBoot)

Boot 37) Boot 骨架项目 如果是 linux 环境&#xff0c;用以下命令即可获取 spring boot 的骨架 pom.xml curl -G https://start.spring.io/pom.xml -d dependenciesweb,mysql,mybatis -o pom.xml也可以使用 Postman 等工具实现 若想获取更多用法&#xff0c;请参考 curl …

Android逆向学习(二)vscode进行双开与图标修改

Android逆向学习&#xff08;二&#xff09;vscode进行双开与图标修改 写在前面 这其实应该还是吾爱的第一个作业&#xff0c;但是写完上一个博客的时候已经比较晚了&#xff0c;如果继续敲机械键盘吵到室友&#xff0c;我怕我看不到明天的太阳&#xff0c;所以我决定分成两篇…

七、Linux中一些符号的含义和宿主目录的介绍

1、Linux中一些符号的含义 在Linux命令行中&#xff0c;会看到如下一些符号&#xff0c;含义如下。 符号含义. 代表当前目录..代表上一层目录&#xff0c;当前目录的父目录-代表前一个目录&#xff0c;刚才从哪个目录cd过来~代表当前用户的宿主目录/代表根目录$普通用户的命…

【高效编程技巧】编程菜鸟和编程大佬的差距究竟在哪里?

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《高效编程技巧》《C语言进阶》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 &#x1f4cb; 前言1.如何写出好的代码&#xff1f;1.2 如何分析一个函数写的怎么样 2. 代码板式的重要性2.1 代码…

③matlab向量和矩阵

目录 手动输入数组 创建等间距向量 数组创建函数 手动输入数组 1.背景 单个称为标量的数值实际上是一个 11 数组&#xff0c;也即它包含 1 行 1 列。 任务 创建一个名为 x 并且值为 4 的变量。 2.您可以使用方括号创建包含多个元素的数组。 x [3 5] x 3 5 任务 …

ChatGPT Prompting开发实战(三)

一、关于chaining prompts与CoT的比较 前面谈到的CoT的推理过程&#xff0c;可以比作是一次性就烹调好一顿大餐&#xff0c;那么接下来要说的“chaining prompts”&#xff0c;其背后的理念是分多次来完成这样一项复杂任务&#xff0c;每次只完成其中一步或者一个子任务。核心…

轻量、便捷、高效—经纬恒润AETP助力车载以太网测试

随着自动驾驶技术和智能座舱的不断发展&#xff0c;高宽带、高速率的数据通信对主干网提出了稳定、高效的传输要求&#xff0c;CAN(FD)、LIN已无法充分满足汽车的通信需求。车载以太网作为一种快速且扩展性好的网络技术&#xff0c;已经逐步成为了汽车主干网的首选。 此外&…

Kubernetes技术--k8s核心技术 Secret

1.概述 Secret 解决了密码、token、密钥等敏感数据的配置问题,而不需要把这些敏感数据暴露到镜像或者 Pod Spec中。Secret可以以 Volume 或者环境变量的方式使用。 作用 加密数据存储在/etc中,使得pod容器以挂载volume方式进行访问。在进行的数据存储中是以base64加密的方式…

yolov2相较于yolov1的改进

目录 前言 BN层取代了Dropout 使用了高分辨率分类器 K-means选定先验框的尺寸 网络结构—darknet19 细粒度的特征 前言 yolov2是在yolov1的基础上进行改进的&#xff0c;主要解决了yolov1定位不准确以及检测重叠的物体极差的情况&#xff0c;总的来说&#xff0c;它有以下…

Gitee注册和使用

个人主页&#xff1a;点我进入主页 专栏分类&#xff1a;C语言初阶 C语言程序设计————KTV C语言小游戏 欢迎大家点赞&#xff0c;评论&#xff0c;收藏。 一起努力&#xff0c;一起奔赴大厂。 目录 1.Gitee 1.1Gitee是什么 1.2Gitee的注册以及远程仓库的创建…

iOS 设置下载部分文件,如何获取完整文件的大小

在视频的需求中&#xff0c;遇到这样一个需求&#xff0c;播放一视频的时候&#xff0c;要预下载 后面10条视频&#xff0c;但是只下载后面十条视频的前面1M 实现方法 1 创建请求时设置cacheLength resource [[IdiotResource alloc] init];resource.requestURL task.request…

docker命令学习

docker vscode插件出现的问题 docker命令 docker images &#xff08;查看所有的镜像&#xff09; docker ps -a &#xff08;查看所有的容器&#xff09; docker ps &#xff08;查看运行的容器&#xff09; docker run imageID docker run --gpus all --shm-size8g -it imag…

day27 String类 正则表达式

String类的getBytes方法 String s "腻害"; byte[] bytes s.getBytes(StandardCharsets.UTF_8); String类的new String方法 String ss "ss我的"; byte[] gbks ss.getBytes("gbk"); String gbk new String(gbks, "gbk"); String类的…

C++学习笔记总结练习:多态与虚函数

1 多态 多态分类 静态多态&#xff0c;是只在编译期间确定的多态。静态多态在编译期间&#xff0c;根据函数参数的个数和类型推断出调用的函数。静态多态有两种实现的方式 重载。&#xff08;函数重载&#xff09;模板。 动态多态&#xff0c;是运行时多态。通过虚函数机制实…

C#,《小白学程序》第八课:列表(List)应用之二“编制高铁列车时刻表”

1 文本格式 /// <summary> /// 车站信息类 class /// </summary> public class Station { /// <summary> /// 编号 /// </summary> public int Id { get; set; } 0; /// <summary> /// 车站名 /// </summary&g…