linux简单理解输入输出重定向

linux简单理解输入输出重定向

linux重定向可以分为输出重定向和输入重定向。在系统中除了标准输入、标准输出、错误输出以外,其他的重定向,都需要指定文件描述符id,也可以称为句柄。

linux中,可以通过查看/proc/进程pid号/fd/下的文件来查看该进程有多少个fd,比如:


bash

体验AI代码助手

代码解读

复制代码

# ls -l /proc/$$/fd/ total 0 lrwx------. 1 root root 64 Jun 3 22:22 0 -> /dev/pts/0 lrwx------. 1 root root 64 Jun 3 22:22 1 -> /dev/pts/0 lrwx------. 1 root root 64 Jun 3 22:22 2 -> /dev/pts/0 #

上述命令中$$表示该进程本身的pid,而该fd文件下,可以看到有012 三个文件,都指向/dev/pts/0,这是一个字符设备文件,表示当前的终端。

输出重定向原理

对于系统而言,任何一个程序都有2个输出,分别是:

  • 文件描述符为1的标准输出
  • 文件描述符为2的错误输出

所以,当执行一个命令输出重定向的时候,比如:


bash

体验AI代码助手

代码解读

复制代码

command >> filename

上述命令是将command命令执行的标准输出结果重定向到filename文件中,你可以理解为在执行该命令的时候,其进程标准输出文件描述符1由默认的/dev/pts/0指向了filename文件,为此可以来写一个程序来试试。

程序如下:


bash

体验AI代码助手

代码解读

复制代码

#!/bin/bash echo "pid: $$" >&2 while true do echo 123 sleep 3 done

这个程序非常简单,首先现输出该脚本的pid到错误输出上,即文件描述符为2,而后定一个无限循环,每隔3秒输出123

在执行的时候,将该文件输出重定向到filename中。


bash

体验AI代码助手

代码解读

复制代码

# bash test.sh >> filename pid: 42699

程序执行会卡主,这是正常的,这是因为有无限循环,每隔3秒会输出123字符串至标准输出上。

而后打开一个新的终端,查看42699fd文件信息。


bash

体验AI代码助手

代码解读

复制代码

# ls -l /proc/42699/fd/ total 0 lrwx------. 1 root root 64 Jun 3 23:41 0 -> /dev/pts/0 l-wx------. 1 root root 64 Jun 3 23:41 1 -> /root/fd/filename lrwx------. 1 root root 64 Jun 3 23:41 2 -> /dev/pts/0 lr-x------. 1 root root 64 Jun 3 23:41 255 -> /root/fd/test.sh #

通过上面执行的结果可以发现,其标准输出,文件描述符为1已经指向一个文件:/root/fd/filename,而非终端字符设备。所以说,在上面案例中,重定向后,实际上是将句柄给改写到文件中,所以屏幕没有输出任何数据。基于此,标准输入和错误输出的原理也是这样的。

输出重定向

输出重定向一般格式为:[n]>[|]filename,其中n是文件描述符,>|表示覆盖保护绕过机制,不过一般不用,即常用的写法为:[n]>filename

比如,将字符串abcdef的标准输出重定向到filename中:


bash

体验AI代码助手

代码解读

复制代码

echo "abcdef" 1> filename

默认情况下,1>可以缩略写为>,这也是常用的写法:


bash

体验AI代码助手

代码解读

复制代码

echo "abcde" > filename

将命令dasdsada的错误结果写入到文件filename中:


bash

体验AI代码助手

代码解读

复制代码

dasdsada 2> filename

因为没有这个命令,所以一定会报错-bash: dasdsada: command not found

对于该重定向而言,它在执行前会清理掉原始内容,从而写入新的内容。

除此之外,还有追加重定向,其格式为[n]>>filename,其中n是文件描述符,>>表示追加,它不会清理掉原有内容。比如将abc追加到文件filename中。


bash

体验AI代码助手

代码解读

复制代码

echo 123 1>> filename

同样的,也可以将1>>缩略写为>>

将命令aaa的错误结果追加写入到文件filename中:


bash

体验AI代码助手

代码解读

复制代码

aaa 2>> filename

输入重定向

linux系统中,任何一个程序的标准输入文件描述符id0,而输入重定向一般格式为[n]<filename,其中n表示文件描述符。

所以,如下命令:


bash

体验AI代码助手

代码解读

复制代码

cat 0< filename

它的意思是将filename文件的内容作为标准输入提供给cat调用,结果是打印了filename的内容,上述命令中的0<可以缩略写为<

不仅如此,还能在循环中,搭配read,将文件的信息按行读取。

比如有以下文件内容:


bash

体验AI代码助手

代码解读

复制代码

# cat filename aa bb cc dd #

有脚本内容如下:


bash

体验AI代码助手

代码解读

复制代码

#!/bin/bash while read ll do echo read_at: ${ll} done 0< filename

上述脚本表示将filename文件作为输入源,供while调用,按照的方式是read命令按行调用,将行内容赋值到ll变量上,这个变量名称可以自定义。

其结果为:


bash

体验AI代码助手

代码解读

复制代码

# bash test.sh read_at: aa read_at: bb read_at: cc read_at: dd #

输入重定向还有一种表达方式是here-documents。表示多行定义输入,其语法为:


bash

体验AI代码助手

代码解读

复制代码

command [n]<<word here doc word

其中n表示文件操作符,如果省略,则使用默认的文件操作符0,而后是关键字<<word是自定义的结束符,让后续读取到word后停止读取。

比如:


bash

体验AI代码助手

代码解读

复制代码

cat <<END 123 456 789 END

输出的结果为


bash

体验AI代码助手

代码解读

复制代码

123 456 789

上述命令中的END是可以替换为任何字符串的,只要后续出现该字符串就会停止输入,注意这个字符,一定是要在单独的一行出现的,不能有其他字符,包括空格。

here-documents会进行命令替换,变量替换等,比如有如下命令:


bash

体验AI代码助手

代码解读

复制代码

# x=123 # cat <<END ${x} $(pwd) aa bb cc END

输出的结果会先进行命令替换,变量替换等,比如将${x}替换为123,将$(pwd)替换为当前目录。如果不想其被替换,则需要添加单引号进行转义。

重定向的顺序

注意看,如下有2条命令:


bash

体验AI代码助手

代码解读

复制代码

ls -l > filename 2>&1


bash

体验AI代码助手

代码解读

复制代码

ls -l 2>&1 > filename

所执行的结果是完全不一样的,第一条命令是将标准输出和错误输出都写入到filename中,而第二条则是将错误输出输出到屏幕上,而将标准输出写入到文件中,如果不是很明白,可以尝试拆解一下命令:

首先,命令的前提是:标准输出 和 错误输出 都在某个设备上,比如pty终端,假设设备为/dev/pts/0,所以文件描述符信息为:

  • 1 -> /dev/pts/0
  • 2 -> /dev/pts/0

然后第一条命令,ls -l > filename 其实是将文件描述符1给指向了文件filename,这个时候,文件描述符信息为:

  • 1 -> filename
  • 2 -> /dev/pts/0

这个时候再使用2>&1表示将错误消息也写入到文件描述符为1的文件中,即filename,所以最后的文件描述符为:

  • 1 -> filename
  • 2 -> filename

而第二条命令,一开始都是输出到某个设备上:

  • 1 -> /dev/pts/0
  • 2 -> /dev/pts/0

这个时候,它将错误输出指向2>&1,而文件描述符为1/dev/pts/0,所以这第一步,就没动过,而第二部则是将标准输出指向filename,即:

  • 1 -> filename
  • 2 -> /dev/pts/0

所以第二条命令,错误输出输出到屏幕上,而将标准输出写入到文件中。

总结

要理解输入输出重定向,一定要理解文件的描述符!对于每个进程,都会产生3个默认的文件描述符,分别是 标准输入、标准输出 和 错误输出,用文件描述符id012 来表示。

其重定向就是修改这些文件描述符的指向,将他们指向到文件中即可。

对于输入重定向而言,有一种表达方式是here-documents,它可以和输出重定向结合,将终端中输入的文件写入到文件中,比如:


bash

体验AI代码助手

代码解读

复制代码

cat 1>> filename 0<<END a b c d e END

表示将终端输入的ab... e字符提供给cat命令,而cat将内容重定向到文件filename中。可以发现上面有1>>表示将标准输出的内容重定向到某个文件,0<<表示将标准输入的内容重定向到某个文件,上述命令中的1>>可以缩写为>>,而0<<可以缩写为<<

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值