你是否见过bash ... 2>&1 1>file.txt
的写法? 还没发现这样的写法有什么问题? 那么恭喜你, 看完本文你又将学会一个新知识!
以引言中命令为例, 2>&1
表示将错误输出重定向到标准输出, 1>file.txt
表示将标准输出重定向到file.txt
文件, 看起来的意思就是将标准输出和错误输出全都重定向到file.txt
?
错啦! 上述命令只会标准输出重定向到file.txt
文件, 而错误输出还是重定向到终端(或者叫做命令行, 控制台, 屏幕). 因为首先解析的是2>&1
,此时的1
指向的还是标准输出, 即终端, 解析到1>file.txt
时, 标准输出才被重定向到file.txt
. 下面我将用一个例子来验证我的结论:
test.sh
是一个简单的脚本, 会把STDOUT
输出到标准输出, 将STDERR
输出到错误输出
$ cat test.sh echo 'STDOUT' >&1 echo 'STDERR' >&2
我们先验证脚本的正确性, 标准输出和错误输出都被正确的捕捉到了, 脚本可以同时输出标准输出和错误输出, 正确性得以验证.
现在我们再来验证我一开始的结论, 执行bash ... 2>&1 1>file.txt
形式的命令, 可以看到错误输出STDERR
被输出到了终端, 而file.txt
中仅有标准输出STDOUT
那么应该怎么改成我们想要的结果呢? 很简单, 将2>&1
和1>file.txt调换个位置即可, 即bash ... 1>file.txt 2>&1
; 或者使用bash ... &>file.txt
, 都可以达到我们想要的效果
重定向另外一个需要注意的事项就是: 执行类似于command > file.txt
的命令时, 会首先判断file.txt
是否存在, 若存在则先清空文件, 若不存在则创建文件, 随后才会执行command
假设有一个已经排好序的文件file.txt
, 我们对这个文件去重的话, 执行uniq file.txt > file.txt
会直接清空文件
想要不生成额外的临时文件做到去重的话, 正确的做法应该是使用管道|
配合tee
命令, 而不是使用重定向