Bash : IO 重定向

程序应该有数据的来源端、数据的目的端(输出结果的地方)已经报告问题的地方,它们分别被称为标准输入(standard input)标准输出(standard output)以及标准错误输出(standard error)。程序不必知道也不用关心它的输入与输出背后是什么设备,当程序运行时,这些标准 IO 就已经打开并准备就绪了。

和 >> 符号把标准输出重定向到文件中 会覆盖掉已经存在的文件中的内容> 则把新的内容追加到已经存在的文件中的内容的尾部

$ : > log.txt

$ >> log.txt

$ >log.txt

$ >error.txt

$ &>log.txt

$ >log.txt >&

$ >log.txt >&

N&N

&-             # 关闭输出文件描述符 n&-,>&-    # 关闭 stdout

/dev/null 2>&1 和 2>&1 >/dev/null

/dev/null 2>/dev/null/dev/null 2>&1

/dev/null/dev/null 的作用是将标准输出 1 重定向到 /dev/null 中,因此标准输出中的内容被完全丢弃了。

&1&1 用到了重定向绑定,采用 & 可以将两个输出绑定在一起,也就是说错误输出将会和标准输出输出到同一个地方。

Linux 在执行 shell 命令之前,就会确定好所有的输入输出位置,解释顺序为从左到右依次执行重定向操作。所以 >/dev/null 2>&1 的作用就是让标准输出重定向到 /dev/null 中,接下来因为错误输出的文件描述符 2 被重定向绑定到了标准输出的描述符 1,所以错误输出也被定向到了 /dev/null 中,错误输出同样也被丢弃了。

&1 >/dev/null&1 >/dev/null 执行的结果和 >/dev/null 2>&1 是不一样的!它的执行过程为:

  1. &1,将错误输出绑定到标准输出上。由于此时的标准输出是默认值,也就是输出到屏幕,所以错误输出会输出到屏幕。
  2. /dev/null,将标准输出1重定向到 /dev/null 中。

#!/bin/E_FILE_ACCESS=<span style="color: #800080">70<span style="color: #000000">
E_WRONG_ARGS=<span style="color: #800080">71

<span style="color: #0000ff">if [ ! -r <span style="color: #800000">"<span style="color: #800000">$1<span style="color: #800000">"<span style="color: #000000"> ] # 判断指定的输入文件是否可读
<span style="color: #0000ff">then
<span style="color: #0000ff">echo <span style="color: #800000">"<span style="color: #800000">Can't read from input file!<span style="color: #800000">"
<span style="color: #0000ff">echo <span style="color: #800000">"<span style="color: #800000">Usage: $0 input-file output-file<span style="color: #800000">"<span style="color: #000000">
exit $E_FILE_ACCESS
<span style="color: #0000ff">fi # 即使输入文件($<span style="color: #800080">1<span style="color: #000000">)没被指定

<span style="color: #0000ff">if [ -z <span style="color: #800000">"<span style="color: #800000">$2<span style="color: #800000">"<span style="color: #000000"> ]
<span style="color: #0000ff">then
<span style="color: #0000ff">echo <span style="color: #800000">"<span style="color: #800000">Need to specify output file.<span style="color: #800000">"
<span style="color: #0000ff">echo <span style="color: #800000">"<span style="color: #800000">Usage: $0 input-file output-file<span style="color: #800000">"<span style="color: #000000">
exit $E_WRONG_ARGS
<span style="color: #0000ff">fi<span style="color: #000000">

exec <span style="color: #800080">4<&<span style="color: #800080">0<span style="color: #000000"> # 保存默认 stdin
exec < $<span style="color: #800080">1<span style="color: #000000"> # 将会从输入文件中读取.

exec <span style="color: #800080">7>&<span style="color: #800080">1<span style="color: #000000"> # 保存默认 stdout
exec > $<span style="color: #800080">2<span style="color: #000000"> # 将写到输出文件中.

假设输出文件是可写的

-----------------------------------------------

<span style="color: #0000ff">cat - | <span style="color: #0000ff">tr a-z A-<span style="color: #000000">Z # 转换为大写

从 stdin 中读取

写到 stdout 上

然而,stdin 和 stdout 都被重定向了

-----------------------------------------------<span style="color: #000000">

exec <span style="color: #800080">1>&<span style="color: #800080">7 <span style="color: #800080">7>&-<span style="color: #000000"> # 恢复 stout
exec <span style="color: #800080">0<&<span style="color: #800080">4 <span style="color: #800080">4<&-<span style="color: #000000"> # 恢复 stdin

恢复之后,下边这行代码将会如预期的一样打印到 stdout 上

<span style="color: #0000ff">echo <span style="color: #800000">"<span style="color: #800000">File \"$1\" written to \"$2\" as uppercase conversion.<span style="color: #800000">"<span style="color: #000000">
exit <span style="color: #800080">0

$ ./upper. .txt out.txt

myfile

><> myfile # 打开 myfile 并且将 fd -n <& -n . >&>&- # 关闭 fd myfile # ==>

#!/bin/E_WRONG_ARGS=<span style="color: #800080">71
<span style="color: #0000ff">if [ -z <span style="color: #800000">"<span style="color: #800000">$1<span style="color: #800000">"<span style="color: #000000"> ]
<span style="color: #0000ff">then
<span style="color: #0000ff">echo <span style="color: #800000">"<span style="color: #800000">Usage: $0 input-file<span style="color: #800000">"<span style="color: #000000">
exit $E_WRONG_ARGS
<span style="color: #0000ff">fi<span style="color: #000000">

Lines=<span style="color: #800080">0

<span style="color: #0000ff">cat <span style="color: #800000">"<span style="color: #800000">$1<span style="color: #800000">" | <span style="color: #0000ff">while<span style="color: #000000"> read line; # 管道会产生子 shell
<span style="color: #0000ff">do<span style="color: #000000"> {
<span style="color: #0000ff">echo<span style="color: #000000"> $line
(( Lines++<span style="color: #000000"> )); # 增加这个变量的值

但是外部循环却不能访问

}
<span style="color: #0000ff">done

<span style="color: #0000ff">echo <span style="color: #800000">"<span style="color: #800000">Number of lines read = $Lines<span style="color: #800000">" # <span style="color: #800080">0<span style="color: #000000">

错误!

<span style="color: #0000ff">echo <span style="color: #800000">"<span style="color: #800000">------------------------<span style="color: #800000">"<span style="color: #000000">
exec <span style="color: #800080">3<> <span style="color: #800000">"<span style="color: #800000">$1<span style="color: #800000">"
<span style="color: #0000ff">while read line <&<span style="color: #800080">3
<span style="color: #0000ff">do<span style="color: #000000"> {
<span style="color: #0000ff">echo <span style="color: #800000">"<span style="color: #800000">$line<span style="color: #800000">"<span style="color: #000000">
(( Lines++<span style="color: #000000"> )); # 增加这个变量的值

现在外部循环就可以访问了

#  没有子shell,现在就没问题了

}
<span style="color: #0000ff">done<span style="color: #000000">
exec <span style="color: #800080">3>&-
<span style="color: #0000ff">echo <span style="color: #800000">"<span style="color: #800000">Number of lines read = $Lines<span style="color: #800000">"<span style="color: #000000">
exit <span style="color: #800080">0

$ ./avoid-subshell. .txt

#!/bin/E_WRONG_ARGS=<span style="color: #800080">71
<span style="color: #0000ff">if [ -z <span style="color: #800000">"<span style="color: #800000">$1<span style="color: #800000">"<span style="color: #000000"> ]
<span style="color: #0000ff">then
<span style="color: #0000ff">echo <span style="color: #800000">"<span style="color: #800000">Usage: $0 input-file<span style="color: #800000">"<span style="color: #000000">
exit $E_WRONG_ARGS
<span style="color: #0000ff">fi<span style="color: #000000">

count=<span style="color: #800080">0

<span style="color: #0000ff">while [ <span style="color: #800000">"<span style="color: #800000">$name<span style="color: #800000">" !=<span style="color: #000000"> xxyy ]
<span style="color: #0000ff">do<span style="color: #000000">
read name
<span style="color: #0000ff">if [ -z <span style="color: #800000">"<span style="color: #800000">$name<span style="color: #800000">" ]; <span style="color: #0000ff">then<span style="color: #000000">
break
<span style="color: #0000ff">fi
<span style="color: #0000ff">echo<span style="color: #000000"> $name
let <span style="color: #800000">"<span style="color: #800000">count += 1<span style="color: #800000">"
<span style="color: #0000ff">done <<span style="color: #800000">"<span style="color: #800000">$1<span style="color: #800000">"
<span style="color: #0000ff">echo <span style="color: #800000">"<span style="color: #800000">$count names read<span style="color: #800000">"<span style="color: #000000">
exit <span style="color: #800080">0

$ ./whileblock. .txt

#!/bin/E_WRONG_ARGS=<span style="color: #800080">71
<span style="color: #0000ff">if [ -z <span style="color: #800000">"<span style="color: #800000">$1<span style="color: #800000">"<span style="color: #000000"> ]
<span style="color: #0000ff">then
<span style="color: #0000ff">echo <span style="color: #800000">"<span style="color: #800000">Usage: $0 input-file output-file<span style="color: #800000">"<span style="color: #000000">
exit $E_WRONG_ARGS
<span style="color: #0000ff">fi

<span style="color: #0000ff">if [ -z <span style="color: #800000">"<span style="color: #800000">$2<span style="color: #800000">"<span style="color: #000000"> ]
<span style="color: #0000ff">then
<span style="color: #0000ff">echo <span style="color: #800000">"<span style="color: #800000">Usage: $0 input-file output-file<span style="color: #800000">"<span style="color: #000000">
exit $E_WRONG_ARGS
<span style="color: #0000ff">fi<span style="color: #000000">

FinalName=<span style="color: #800000">"<span style="color: #800000">xxyy<span style="color: #800000">"<span style="color: #000000">
line_count=$(<span style="color: #0000ff">wc <span style="color: #800000">"<span style="color: #800000">$1<span style="color: #800000">" | <span style="color: #0000ff">awk <span style="color: #800000">'<span style="color: #800000">{ print $1 }<span style="color: #800000">'<span style="color: #000000">)

<span style="color: #0000ff">for name <span style="color: #0000ff">in $(<span style="color: #0000ff">seq<span style="color: #000000"> $line_count)
<span style="color: #0000ff">do<span style="color: #000000">
read name
<span style="color: #0000ff">echo <span style="color: #800000">"<span style="color: #800000">$name<span style="color: #800000">"
<span style="color: #0000ff">if [ <span style="color: #800000">"<span style="color: #800000">$name<span style="color: #800000">" = <span style="color: #800000">"<span style="color: #800000">$FinalName<span style="color: #800000">"<span style="color: #000000"> ]
<span style="color: #0000ff">then<span style="color: #000000">
break
<span style="color: #0000ff">fi
<span style="color: #0000ff">done < <span style="color: #800000">"<span style="color: #800000">$1<span style="color: #800000">" > <span style="color: #800000">"<span style="color: #800000">$2<span style="color: #800000">"<span style="color: #000000">
exit <span style="color: #800080">0

$ ./forblock. .txt out.txt

/dev/null 2>&1 是什么鬼?

相关文章

用的openwrt路由器,家里宽带申请了动态公网ip,为了方便把2...
#!/bin/bashcommand1&command2&wait从Shell脚本并行...
1.先查出MAMP下面集成的PHP版本cd/Applications/MAMP/bin/ph...
1、先输入locale-a,查看一下现在已安装的语言2、若不存在如...
BashPerlTclsyntaxdiff1.进制数表示Languagebinaryoctalhexa...
正常安装了k8s后,使用kubect工具后接的命令不能直接tab补全...