引言
你是否見過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
命令, 而不是使用重定向