当前位置: 首页 > 科技观察

深入理解LinuxI-O重定向

时间:2023-03-19 16:31:11 科技观察

文件描述符只是文件系统分配给它的一个数字,用于跟踪打开的文件。也可以理解为文件指针的简化版,类似于C语言的文件句柄的概念。在Linux中总是默认打开3个“文件”,stdin(键盘)、stdout(屏幕)和stderr(错误信息输出到屏幕)。这3个文件和其他打开的文件可以重定向。重定向,简单地说,就是捕获一个文件、命令、程序、脚本或脚本中代码块的输出,然后将这些输出作为输入发送给另一个文件、命令、程序或脚本。每个打开的文件都分配有一个文件描述符。stdin、stdout和stderr的文件描述符分别为0、1和2。除了这3个文件,文件描述符3到9是为其他需要打开的文件保留的。在某些情况下,将这些额外的文件描述符分配给stdin、stdout或stderr作为临时复制链接可能很有用。在复杂的重定向和刷新之后,它们需要恢复到正常状态。redirect>file将标准输出重定向到一个文件。如果文件不存在,则创建它,否则覆盖它。创建一个包含目录树列表的文件:ls-lR>dir-tree.list清空文件::>file这是一个>操作,它将文件file更改为空文件(即size为0)。如果该文件不存在,则会创建一个零长度文件(与touch的效果相同)。:是一个占位符,不产生任何输出。也可以省略:占位符:>file与上面的:>效果相同,但有些shell(如bash)可能不支持这种形式。>>file将stdout重定向到一个文件。如果文件不存在,则创建它,如果存在,则将其附加到文件中。script.sh1>filename#Redirectstdouttofile"filename".script.sh1>>filename#Redirectandappendstdouttofile"filename".script.sh2>filename#Redirectstderrtofile"filename".script.sh2>>filename#redirect并将stderr附加到文件“filename”。&>file将stdout和stderr都重定向到file:script.sh&>/dev/nullm>filem是一个文件描述符,如果没有明确指定默认是1。file是一个文件名。文件描述符m被重定向到文件file。script.sh2>error.logm>&nm是一个文件描述符,如果没有明确指定则默认为1。n是另一个文件描述符。script.sh2>&1将stderr重定向到stdout。将错误消息的输出发送到标准输出指向的位置。exec6<>Filescript.sh>&6默认情况下,将文件描述符1(stdout)重定向到6。传递到stdout的所有输出都发送到6。是成对命令,通常组合使用。0file打开文件file并为其分配文件描述符j以读写文件。如果文件文件不存在,则创建它。如果未指定文件描述符j,则默认为标准输入0。echo1234567890>File###WritestringtoFile.exec3<>File###OpenFileandassignfd3toit.read-n4<&3###Onlyread4characters.echo-n.>&3###写一个decimalpoint.exec3>&-###Closefd3.catFile###==>1234.67890(注:以上命令输出结果与原文有出入,原因不详)管道与>非常相似,但实际上更一般。当您想将命令、脚本、文件和程序链接在一起时很有用。cat*.txt|sort|uniq>result-file上面的命令对所有.txt文件的输出进行排序并删除重复行。***将结果保存到结果文件中。输入/输出重定向和/或管道的多个实例可以组合在同一行上:commandoutput-file等效于:output-file但这不是标准的,某些shell可能不支持。多个输出流可以重定向到单个文件:ls-yz>>command.log2>&1将错误选项yz的结果放入文件command.log中。由于stderr被重定向到该文件,因此所有错误消息也都指向该文件。请注意,以下示例不会给出相同的结果:ls-yz2>&1>>command.log输出错误消息,但不会写入文件。命令的输出(如果有)被写入文件command.log。如果同时重定向stdout和stderr,不同的命令顺序会带来不同的结果。关闭文件描述符n<&-关闭输入文件描述符n。0<&-或<&-关闭标准输入。n>&-关闭输出文件描述符n。1>&-或>&-关闭标准输出。子进程继承打开的文件描述符。这就是管道工作的原因。如果你想阻止文件描述符被继承,你可以关闭它。只需将stderr重定向到管道即可。exec3>&1###保存stdout的当前“值”(将fd3指向与fd0相同的目标)ls-l2>&1>&33>&-|grepbad3>&-###Closefd3for'grep'###^^^^^^^^###(但不要关闭'ls',正常输出内容不会被grep影响)ls-l2>&1>&3|grepbad###输出内容会被转移到fd3,不会受grep影响lsbadabc-l2>&1>&3|grepbad###stderroutputviafd1,willbeaffectedbygrepexec3>&-###对于脚本的其余部分,关闭它使用文件描述符5可能会导致问题。当Bash使用exec创建子进程时,子进程继承文件描述符5(请参阅ChetRamey的存档电子邮件:RE:文件描述符5保持打开状态)。***仍然不要理会这个特定的文件描述符5。