Linux重定向:深入理解与实践

news2024/10/6 23:26:49

 

                                                           🎬慕斯主页修仙—别有洞天 

                                                         ♈️今日夜电波:晴る—ヨルシカ

                                                                0:20━━━━━━️💟──────── 4:30
                                                                    🔄   ◀️   ⏸   ▶️    ☰  

                                      💗关注👍点赞🙌收藏您的每一次鼓励都是对我莫大的支持😍


 

目录

引入

文件描述符的分配规则

重定向理解

什么是重定向?

输出重定向

输入重定向

追加重定向

dup2

重新理解‘输入’和‘输出’重定向

完整的重定向格式

标准输出重定向

标准错误重定向

标准输出以及标准错误重定向同一文件


引入

文件描述符的分配规则

        在Linux系统中,文件描述符是一个数字,这个数字是用于表示打开的文件、管道和网络连接等进程所操作对象的标识符。文件描述符的分配规则遵循最小分配原则,也就是寻找未被占用的最小的文件描述符来使用。

        在Linux进程中,默认会有三个已经打开的文件描述符,对应的是标准输入(0)、标准输出(1)和标准错误(2)。这三个文件描述符分别对应键盘、显示器和打印机等物理设备。

        当我们需要打开新的文件时,系统会根据最小分配原则找到下一个可用的文件描述符进行分配。一般来说,新打开的文件会占用文件描述符3(如果0、1、2尚未被占用),接着是文件描述符4,以此类推。特别的,如果0、1或2已被关闭,那么新打开的文件的文件描述符可能会被赋值为0或1或2。

        需要注意的是,虽然文件描述符是连续分配且依次增大的,但它们的起始值并不从0开始,而是从3开始。

        🌰

        在学习完Linux下的系统文件操作后,我们都知道Linux下一切皆文件,我们可以对文件进行打开、读、写、关闭等操作。而系统默认会帮我们打开三个文件,分别为标准输入、标准输出和标准出错处理,即:stdin、stdout、stderr。这三个文件分别对应文件描述符0、1、2。那么如果我们关闭了其中的一个文件,再额外打开个新的文件会这么样呢?如下:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define FI "fi.txt"
int main()
{
	umask(0);
    close(1);//关闭输出流
    int fd = open(FI, O_WRONLY | O_CREAT | O_TRUNC, 0666);
    printf("hello!\n");
    printf("hello!\n");
    printf("hello!\n");
    printf("hello!\n");
    printf("hello!\n");
    printf("hello!\n");
    printf("hello!\n");
    printf("my fd is %d\n",fd); 
    return 0;
}

        对上述代码的情况可见:我们关闭了输出流的文件,新打开了一个文件,而使用printf进行打印操作。需要注意的是:printf、scanf都是默认的输入输出流,也就是说他们是按照stdin、stdout来进行对应的操作的。而此时printf非但没有把字符打印到显示器上反而打印到了新开的那个文件里,并且对应的文件描述符居然是1!这就说明了新开文件的文件描述符是遵守有空就补、从小到大使用的规律。

        大致的操作如下:

        对此,这也引出了我们重定向的概念—重定向是一种改变标准输入或输出默认执行方式的操作,无需大量的鼠标和键盘操作就可以完成数据的转移。

重定向理解

什么是重定向?

        在Linux系统中,重定向的本质是修改原来默认的执行方式,对系统命令的执行过程进行重新定义。它主要涉及两个方面:输入重定向和输出重定向。

  • 输入重定向:指的是将一个文件的内容导入到命令中作为输入数据。这种方式可以使得命令的执行不再依赖键盘的输入,而是读取来自指定文件的数据,从而提高了效率和便捷性。
  • 输出重定向:指的是将命令的执行结果保存到文件中,而不是直接显示在显示器上。这种方式可以将命令的输出信息保存下来,以供后续分析和使用,避免了信息的丢失。

        说大白话就是:修改特性文件fd下标的内容,上层fd不变,底层fd指向的内容在改变

输出重定向

        我们通过关闭文件描述符1或者2,然后打开一个新的文件使得通过printf输出的内容输出到fi.txt文件中。

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define FI "fi.txt"
int main()
{
	umask(0);
    close(1);//关闭输出流
    int fd = open(FI, O_WRONLY | O_CREAT | O_TRUNC, 0666);
    printf("output redirection!\n");
    printf("output redirection!\n");
    printf("output redirection!\n");
    printf("my fd is %d\n",fd); 
    return 0;
}

输入重定向

        我们通过关闭文件描述符0,然后打开一个新的文件通过scanf从fi.txt中输入内容,然后再通过printf输出到显示器上。

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define FI "fi.txt"
int main()
{
	umask(0);
    close(1);//关闭输入流
    int fd = open(FI, O_RDONLY , 0666);
	char *st;
    scanf("%s",st);
    printf("%s\n",st);
    scanf("%s",st);
    printf("%s\n",st);
    scanf("%s",st);
    printf("%s\n",st);
    printf("my fd is %d\n",fd); 
    return 0;
}

追加重定向

        本质还是和输出重定向一样关闭文件描述符1或者2,但是需要注意的是我们更改了打开文件的操作,把清空操作改为了追加操作。 O_TRUNC -> O_APPEND

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define FI "fi.txt"
int main()
{
	umask(0);
    close(1);//关闭输出流
    int fd = open(FI, O_WRONLY | O_CREAT | O_APPEND,  0666);
    printf("append redirection!\n");
    printf("append redirection!\n");   
    printf("append redirection!\n");
    printf("my fd is %d\n",fd); 
    return 0;
}

dup2

        dup2函数是Unix/Linux系统中的一个系统调用函数,作用是复制文件描述符,并将其指定为新的文件描述符。其具体功能是将一个已存在的文件描述符复制到另一个新的文件描述符上,并且可以自定义新文件描述符的编号。系统中的手册如下:

        这个函数在C语言中常用于实现输入输出重定向。例如,可以先使用open()函数打开需要重定向的文件,然后使用dup2()函数将指定的文件描述符复制到新的文件描述符。这样就可以改变一个进程的标准输入、标准输出和标准错误输出的文件描述符指向,进而实现重定向的功能。

        dup2函数的原型为 int dup2 (int oldfd, int newfd); 其中,oldfd参数表示要被复制的文件描述符,newfd参数表示新的文件描述符。如果newfd已经打开,则先将其关闭。如果newfd等于oldfd,则dup2返回newfd, 而不关闭它。

        需要注意的是:dup2函数是dup()函数的“升级版“,因为与dup()只能复制一次不同,dup2可以无限次复制文件描述符。此外,如果复制成功,dup2函数会返回最小的尚未被使用过的文件描述符。

 

        🌰

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define FI "fi.txt"
int main()
{
	umask(0);
    int fd = open(FI, O_WRONLY | O_CREAT | O_APPEND,  0666);
    dup2(fd,1);
    printf("append redirection!\n");
    printf("append redirection!\n");   
    printf("append redirection!\n");
    printf("my fd is %d\n",fd); 
    close(fd);
    return 0;
}

重新理解‘输入’和‘输出’重定向

        在Linux中,>、>>和<、<<是重定向操作符,用于将命令的输出或输入重定向到文件或管道。

        - >:将命令的标准输出重定向到一个文件中,如果该文件不存在则创建它,如果存在则覆盖原有内容。例如:ls > file.txt 会将ls命令的输出保存到file.txt文件中。

        - >>:将命令的标准输出追加到一个文件中,如果该文件不存在则创建它。例如:ls >> file.txt 会将ls命令的输出追加到file.txt文件中。

        - <:将一个文件的内容作为命令的标准输入。例如:sort < file.txt 会将file.txt文件的内容作为sort命令的输入。

        - <<:将多行文本作为命令的标准输入。例如:echo -e "line1 line2 line3" | cat << EOF 会将EOF标记之间的文本作为cat命令的输入。

        通过上面我们对于重定向的理解,我们也从本质上理解了重定向实际上做的是什么操作,即:修改底层fd的指向。接下来我们进一步学习对于输入和输出的重定向!

完整的重定向格式

        实际上,完整的重定向格式如下:

命令 fd>/>>/</<< 命令

        🌰

标准输出重定向

标准错误重定向

标准输出以及标准错误重定向同一文件

 


                         感谢你耐心的看到这里ღ( ´・ᴗ・` )比心,如有哪里有错误请踢一脚作者o(╥﹏╥)o! 

                                       

                                                                        给个三连再走嘛~  

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

力扣hot100 相交链表 思维题

Problem: 160. 相交链表 文章目录 思路复杂度&#x1f496; Ac Code 思路 &#x1f468;‍&#x1f3eb; 参考题解 &#x1f469;‍&#x1f3eb; 参考图解 复杂度 时间复杂度: O ( n m ) O(nm) O(nm) 空间复杂度: 添加空间复杂度, 示例&#xff1a; O ( 1 ) O(1) O(…

2024年第十二届亚洲机械与材料工程国际会议(ACMME 2024)即将召开!

时间&#xff1a;2024年6月14-17日 地点&#xff1a;日本京都先端科学大学太秦校区 会议官网&#xff1a;第11届ACMME |日本京都 2024年第十二届亚洲机械与材料工程会议 &#xff08;ACMME 2024&#xff09;将于2024年6月14日-17日在日本京都先端科学大学召开。亚洲机械与材料…

三、arcgispro二次开发创建第一个工程

忙了几天&#xff0c;总算可以创建第一工程了。 步骤一&#xff1a; 步骤二&#xff1a; 工具介绍&#xff1a; 项目创建成功&#xff1a;项目目录在解决方案资源管理器中&#xff0c;整个工具都是动态可调整的&#xff0c;如下图&#xff1a; 想把窗口放哪里就把鼠标移到红…

CorelDRAW Graphics Suite2024专业图形设计软件Mac/Windows版

以激情为创造动力&#xff0c;以目的为设计导向。“对专业的图形设计人士来说&#xff0c;CorelDRAW 是市面上最易于使用的软件。 我用它设计过标牌、横幅、T 恤&#xff0c;甚至 45 英尺长的房车图形&#xff01;” 使用 CorelDRAW 全新的聚焦模式&#xff0c;现在可以单独编…

[设计模式Java实现附plantuml源码~创建型] 产品族的创建——抽象工厂模式

前言&#xff1a; 为什么之前写过Golang 版的设计模式&#xff0c;还在重新写Java 版&#xff1f; 答&#xff1a;因为对于我而言&#xff0c;当然也希望对正在学习的大伙有帮助。Java作为一门纯面向对象的语言&#xff0c;更适合用于学习设计模式。 为什么类图要附上uml 因为很…

Ubuntu系统pycharm以及annaconda的安装配置笔记以及问题集锦(更新中)

Ubuntu 22.04系统pycharm以及annaconda的安装配置笔记以及问题集锦 pycharm安装 安装完之后桌面上并没有生成图标 后面每次启动pycharm都要到它的安装路径下的bin文件夹下&#xff0c; cd Downloads/pycharm-2018.1.4/bin然后使用sh命令启动脚本程序来打开pycharm sh pycha…

FindMy技术与相机结合

FindMy是苹果公司提供的设备追踪服务&#xff0c;用来帮助用户定位丢失的设备。自苹果公司开放Findmy网络之后&#xff0c;FindMy技术便与各种生活设备相结合&#xff0c;比如与相机的结合。 想象一下&#xff0c;你正在外出办事或者旅行时&#xff0c;突然意识到相机丢了&…

vectorCast——CBA功能实现代码手动覆盖

选择被测文件&#xff0c;点击右键&#xff0c;选择add coverage analysis.选择添加覆盖分析后&#xff0c;会自动打开CBA。此时就可以在代码里选择没有覆盖的代码&#xff0c;勾选后填写未覆盖分析并保存&#xff0c;就可以实现代码覆盖了。查看覆盖率报告。 手动覆盖代码完成…

uniapp组件库Popup 弹出层 的使用方法

目录 #平台差异说明 #基本使用 #设置弹出层的方向 #设置弹出层的圆角 #控制弹窗的宽度 | 高度 #内容局部滚动 #API #Props #Event 弹出层容器&#xff0c;用于展示弹窗、信息提示等内容&#xff0c;支持上、下、左、右和中部弹出。组件只提供容器&#xff0c;内部内容…

C语言总结十一:自定义类型:结构体、枚举、联合(共用体)

本篇博客详细介绍C语言最后的三种自定义类型&#xff0c;它们分别有着各自的特点和应用场景&#xff0c;重点在于理解这三种自定义类型的声明方式和使用&#xff0c;以及各自的特点&#xff0c;最后重点掌握该章节常考的考点&#xff0c;如&#xff1a;结构体内存对齐问题&…

Java 数组原理内存图

Java 虚拟机的内存划分 为了提高运算效率&#xff0c;就对空间进行了不同区域的划分&#xff0c;因为每一片区域都有特定的处理数据方式和内存管理方式。 JVM 的内存划分 数组在内存中的存储 一个数组内存图 public static void main(String[] args) {int[] nums new int[] {1…

64位ATT汇编语言as汇编ld链接,执行报错Segmentation fault

absCallAndPrintAbsAsLd.s里边的内容如下&#xff1a; .section .datastringToShow:.ascii "The abs of number is %d\n\0" .global _start .section .text _start:pushq %rbpmovq %rsp,%rbpmovq $-5,%rdicall absmovq $stringToShow,%rdimovq %rax,%rsicall printf…

鸿蒙星河版启航,开发者驶入生态新征程

操作系统市场的气候已经不同以往。在鸿蒙决定不再兼容安卓之后&#xff0c;这里正欲长出一片全新的天地。 四年前&#xff0c;华为鸿蒙系统横空出世&#xff0c;彼时它还不完全与安卓和iOS的性质划等号&#xff0c;而是定义为物联网操作系统。而如今的华为鸿蒙要改写故事篇章&…

关于C语言整型提升的讲解

目录 1.什么是整型提升 2.整型提升的意义 3.整型提升是怎么提升的 4.整型提升的实例 1.什么是整型提升 C语言中的整型算术运算总是以缺省&#xff08;默认&#xff09;整型类型的精度来进行的。为了获得这个精度&#xff0c;表达式中的字符和短整型操作数在使用之前会被转换…

go语言(十一)----面向对象继承

一、面向对象继承 写一个父类 package mainimport "fmt"type Human struct {name stringsex string }func (this *Human) Eat() {fmt.Println("Human.Eat()...") }func (this *Human) Walk() {fmt.Println("Human.Walk()...") }func main() {h…

JNPF低代码开发平台总体架构介绍

目录 一、JNPF介绍 二、团队能力 三、技术选型 1.后端技术栈 2.前端技术栈 3.数据库支持 四、JNPF界面示意图 五、开发环境 一、JNPF介绍 JNPF是一款企业级低代码开发平台。基于Springboot、Vue技术&#xff0c;采用微服务、前后端分离架构&#xff0c;基于可视化数据建…

虹科分享 | Redis与MySQL协同升级企业缓存

文章速览&#xff1a; MySQL为什么需要Redis EnterpriseRedis Enterprise带来哪些优势Redis Enterprise与MySQL协同 传统的MySQL数据库在处理大规模应用时已经到了瓶颈&#xff0c;Redis Enterprise怎样助力突破这一瓶颈&#xff1f;Redis Enterprise与MYSQL共同用作企业级缓存…

ChatGPT 如何解决 “Something went wrong. lf this issue persists ….” 错误

Something went wrong. If this issue persists please contact us through our help center at help.openai.com. ChatGPT经常用着用着就出现 “Something went wrong” 错误&#xff0c;不管是普通账号还是Plus账号&#xff0c;不管是切换到哪个节点&#xff0c;没聊两次就报…

什么是中间件?

文章目录 为什么需要中间件&#xff1f;中间件生态漫谈数据库中间件读写分离分库分表引进数据库中间件MyCat 服务端代理模式ShardingJDBC 客户端代理模式 总结 IT 系统从单体应用逐渐向分布式架构演变&#xff0c;高并发、高可用、高性能、分布式等话题变得异常火热&#xff0c…

开源项目_一键发布 markdown 到各个平台_Wechatsync

1 使用场景 最近文章更新比较频繁&#xff0c;基本是日更。因此花费了相当多的时间在不同平台之间同步。时间主要消耗在&#xff1a;需要大致浏览一遍文章内容&#xff0c;另外某些平台需要手动上传图片&#xff0c;有时还需要调整排版。 为了解决这个问题&#xff0c;我选择…