1.tee 多重定向
tee [options] FILE1 FILE2 FILE3...
tee 的作用是将一份标准输入多重定向, 一份重定向到标准输出 / dev/stdout, 然后还将标准输入重定向到每个文件 FILE 中.
例如:
- $ cat alpha.log | tee file1 file2 file3 | cat
- $ cat alpha.log | tee file1 file2 file3>/dev/null
上面第一个命令将 alpha.log 的文件内容重定向给 file{1..3}和标准输出通过管道传递给 cat;
上面第二个命令将 alpha.log 的文件内容重定向给 file{1..3}和 / dev/null.
tee 重定向给多个命令
写多了脚本的人可能遇到过这样一种需求: 将一份标准输入, 重定向到多个命令中去. 大概是这样的:
| CMD1
↗
INPUT | tee
↘
| CMD2
其实 bash 自身的特性就能实现这样的需求, 通过重定向到子 shell 中, 就能模拟一个文件重定向行为:
cat alpha.txt | tee>(grep -E "a|b")>(grep -E "d|b|c")
上面的命令将 alpha.txt 文件内容重定向为 3 份: 一份给第一个 grep 命令, 一份给第二个 grep 命令, 一份给标准输出. 假如 alpha.txt 的内容是 a b c d e5 个字母分别占用 5 行(每行一个字母), 上面的输出结果如下:
- a
- b
- c
- d
- e # 前 5 行是重定向到 / dev/stdout 的
- a
- b # 这 2 行是重定向给第一个 grep 后的执行结果
- b
- c
- d # 这 3 行是重定向给第二个 grep 后的执行结果
如果不想要给标准输出的那份重定向, 加上>/dev/null:
cat alpha.txt | tee>(grep -E "a|b")>(grep -E "d|b|c")>/dev/null
tee 重定向给多个命令时的问题
但是必须注意, tee 将数据重定向给不同命令时, 这些命令是独立执行的, 它们都会各自打开一个属于自己的 STDOUT, 如果它们都重定向到标准输出, 由于涉及到多个不同的 / dev/stdout, 它们的结果将出现两个问题:
不保证有序性
因为跨了命令, 交互式模式下 (默认标准输出为屏幕) 可能会出现命令行隔断的问题(非交互式下不会有问题)
例如:
- $ cat alpha.txt | tee>(grep -E "a|b")>(grep -E "d|b|c")>/dev/null
- $ a # 结果直接出现在提示符所在行
- b
- b
- c
- d
- $ cat alpha.txt | tee>(grep -E "a|b")>(grep -E "d|b|c")>/dev/null
- b
- c # 这次的结果和上次的顺序不一样
- d
- a
- b
这两个问题, 在写脚本过程中必须解决.
对于第二个问题: 不同 / dev/stdout 同时输出时在屏幕上交叉输出的问题, 只需将它们再次重定向走即可, 这样两份不同的 / dev/stdout 都再次同时作为一份标准输入:
$ cat alpha.txt | tee>(grep -E "a|b")>(grep -E "d|b|c")>/dev/null | cat
对于第一个问题: 不同 / dev/stdout 同时输出时, 输出顺序的随机性, 这个没有好方法, 只能在各命令行中将各自的结果保存到文件中:
$ cat alpha.txt | tee>(grep -E "a|b">file1)>(grep -E "d|b|c">file2)>/dev/null
所以, tee 在重定向到多个命令中是有缺陷的, 或者说用起来非常不方便, 只要将各命令的结果各自保存时, 才能一切按照自己的预期进行. 那么, pee 登场了, 多重定向非常好用的一个命令.
2.pee 代替 tee
pee 是 moreutils 包中的一个小工具, 先安装它(epel 源中有):
yum -y install moreutils
在 man pee 中, pee 的作用是将标准输入 tee 给管道. 语法:
pee ["cmds"]
不是很好理解, 可以通过几个示例直接感受它的用法.
- $ cat alpha.txt | pee 'grep -E"a|b"''grep -E"d|b|c"'
- a
- b
- b
- c
- d
所以, 它的基本用法是 pee "CMD1" "CMD2".
如果想将结果保存到文件, 只需加一个命令即可, 例如下面的 cat>myfile.
$ cat alpha.txt | pee 'grep -E"a|b"''grep -E"d|b|c"''cat>myfile'
和 tee 有同样的问题, 如果各命令都没有指定自己的标准输出重定向, 它们将各自打开一个属于自己的 / dev/stdout, 同样会有多个 / dev/stdout 同时输出时结果数据顺序随机性的问题, 但是不会有多个 / dev/stdout 同时输出时交互式的隔断性问题, 因为 pee 会收集各个命令的标准输出, 然后将收集的结果作为自己的标准输出.
pee 和 tee 最大的不同, 在于 pee 将来自多个不同命令的结果作为 pee 自己的标准输出, 所以下面的命令是可以像普通命令一样进行重定向的.
INPUT | pee CMD1 CMD2>/FILE
而 tee 则不同, 是将 cmd1 和 cmd2 的结果放进标准输出(假设各命令自身没有使用重定向), 保存到 FILE 中的是 tee 读取的标准输入.
INPUT | tee>(cmd1)>(cmd2)>/FILE
所以, 想要重定向 tee 中 cmd1 和 cmd2 的总结果, 必须使用额外的管道, 或者将整个 tee 放进子 shell.
- INPUT | tee>(cmd1)>(cmd2)>/dev/null | cat>FILE1
- INPUT | ( tee>(cmd1)>(cmd2)>/dev/null )>/FILE1
来源: https://www.cnblogs.com/f-ck-need-u/p/9749882.html