在我们理解输入输出重定向的时候要知道我们共有三个:
0: Standard Input (STDIN)
1: Standard Output (STDOUT)
2: Standard Error Output (STDERR)
需要注意并记住的知识点是:
(1)
<< 又是啥呢?这是所谓的 HERE Document ,它可以让我们输入一段文本,直到读到 << 后指定的字符串。比方说:
$ cat <<FINISH
first line here
second line there
third line nowhere
FINISH
这样的话,cat 会读进 3 行句子,而无需从 keyboard 读进数据且要等 ^d 结束输入。
(2)
* 2>&1 就是将 stderr 并进 stdout 作输出
* 1>&2 或 >&2 就是将 stdout 并进 stderr 作输出
(提示:将 &>换成 >& 也行啦~~! )
(3)
在 linux 档案系统里,有个设备档位于 /dev/null 。
(4)
$ echo "some text here" > file
$ cat < file
some text here
$ cat < file > file.bak
$ cat < file.bak
some text here
$ cat < file > file
$ cat < file
前面提到:$ cat < file >; file 之后原本有内容的档案结果却被洗掉了﹗要理解这一现像其实不难,这只是 priority 的问题而已:
* 在 IO Redirection 中,stdout 与 stderr 的管道会先准备好,才会从 stdin 读进资料。
也就是说,在上例中,>; file 会先将 file 清空,然后才读进 < file ,但这时候档案已经被清空了,因此就变成读不进任何数据了...
哦~~~ 原来如此~~~~ ^_^ 那... 如下两例又如何呢?
$ cat <> file
$ cat < file >> file
我的理解是<>行为如下
1.不会把文件清空(不同于>)
2.会从第一个字节来写,而不是append.(不同于>>)
1<>file,表示把file打开,并指向fd1, fd1即标准输出,也就是所有影响标准输出的操作都会体现到file中
(4)
pipe line管道
在 cm1 | cm2 | cm3 ... 这段 pipe line 中,若要将 cm2 的结果存到某一档案呢?
若你写成 cm1 | cm2 >; file | cm3 的话,
那你肯定会发现 cm3 的 stdin 是空的﹗(当然啦,你都将水管接到别的水池了﹗)
聪明的你或许会如此解决:
cm1 | cm2 > file ; cm3 < file
是的,你的确可以这样做,但最大的坏处是:这样一来,file I/O 会变双倍﹗
在 command 执行的整个过程中,file I/O 是最常见的最大效能杀手。凡是有经验的 shell 操作者,都会尽量避免或降低 file I/O 的频率。
那,上面问题还有更好方法吗?
有的,那就是 tee 命令了。
* 所谓 tee 命令是在不影响原本 I/O 的情况下,将 stdout 复制一份到档案去。
因此,上面的命令行可以如此打:
cm1 | cm2 | tee file | cm3
在预设上,tee 会改写目标档案,若你要改为增加内容的话,那可用 -a 参数达成。
附表:
- 常用文件重定向命令
- command > filename 把把标准输出重定向到一个新文件中
- command >> filename 把把标准输出重定向到一个文件中(追加)
- command 1 > fielname 把把标准输出重定向到一个文件中
- command > filename 2>&1 把把标准输出和标准错误一起重定向到一个文件中
- command 2 > filename 把把标准错误重定向到一个文件中
- command 2 >> filename 把把标准错误重定向到一个文件中(追加)
- command >> filename 2>&1 把把标准输出和标准错误一起重定向到一个文件中(追加)
- command < filename >filename2 把commond命令以filename文件作为标准输入,以filename 2文件
- 作为标准输出
- command < filename 把commond命令以filename文件作为标准输入
- command << delimiter 把从标准输入中读入,直至遇到delimiter分界符
- command <&m 把把文件描述符m作为标准输入
- command >&m 把把标准输出重定向到文件描述符m中
- command <&- 把关闭标准输入