2012-06-09 21 views
20

我想將bash腳本中的printf的輸出指向stderr而不是stdout我應該使用什麼方法在bash腳本中使用'printf'將錯誤消息寫入'stderr'?

我是不是詢問重定向stderrstdout從哪裏他們目前路由。我只希望能夠將printf的輸出發送到stderr而不是默認的stdout

我試驗了一下,發現1>&2附加到printf,如下面的例子所示,似乎做我想做的。但是,我有沒有使用bash的經驗。所以我的主要的問題是如果有一個「更好」的方式在bash做到這一點?

作者:「better」我的意思是還有另一種更常用,更常規或更慣用的方法嗎?一個更有經驗的bash程序員如何做到這一點?

#!/bin/bash 
printf "{%s} This should go to stderr.\n" "$(date)" 1>&2 
printf "[(%s)] This should go to stdout.\n" "$(date)" 

我也有一個二次問題。我問的不是很多,因爲我需要需要才能知道,但更多的是因爲我只是好奇而且想更好地瞭解發生的事情。

上面的代碼似乎只能在shell腳本中運行。當我從命令行嘗試它時,它似乎不起作用。

這裏是我的意思的一個例子。

[email protected]:~$ printf "{%s} Sent to stderr.\n" "$(date)" 1>&2 2> errors.txt 
{Sat Jun 9 14:08:46 EDT 2012} Sent to stderr. 
[email protected]:~$ ls -l errors.txt 
-rw-rw-r-- 1 irrational irrational 0 Jun 9 14:39 errors.txt 

我希望上面的printf命令沒有輸出,因爲輸出應該去stderr,這反過來應該去到一個文件中。但是這並沒有發生。咦?

回答

22

首先,是的,1>&2是正確的做法。

其次,您的1>&2 2>errors.txt示例不起作用的原因是由於確切的重定向的具體細節。

1>&2的意思是「使文件句柄1指向文件句柄2當前所處的任何位置」 - 即現在已寫入stdout的內容轉到stderr。 2>errors.txt的意思是「打開一個文件句柄至errors.txt,並使文件句柄2指向它」 - 即現在寫入stderr的東西現在進入errors.txt。但是文件句柄1完全不受影響,所以寫入stdout的東西仍然會轉到stderr。

正確的事情是2>errors.txt 1>&2,這將使寫入到兩個標準錯誤和標準輸出去errors.txt,因爲第一個操作將是「開放errors.txt,使標準錯誤指向它」,第二個操作將是「使stdout指向stderr現在指向的位置「。

+0

是的,事實上,'2> errors.txt 1>&2'就是我應該使用的。事後看來我感到很愚蠢,但這似乎是我必須繼續做出的那些愚蠢的錯誤之一,直到正確的方式對我變得「顯而易見」。 ;-)非常感謝您的洞察力。 –

6
  1. 這對我來說似乎是合理的。你不需要1,雖然 - 它會工作原樣,但它暗示:

    printf "{%s} This should go to stderr.\n" "$(date)" >&2 
    
  2. 你有訂單的,操作的問題:

    $ printf "{%s} Sent to stderr.\n" "$(date)" 2> errors.txt 1>&2 
    $ ls -l errors.txt 
    -rw-r--r-- 1 carl staff 47 Jun 9 11:51 errors.txt 
    $ cat errors.txt 
    {Sat Jun 9 11:51:48 PDT 2012} Sent to stderr. 
    
+0

+1。有關更多信息,請參閱http://www.gnu.org/software/bash/manual/bashref.html#Redirections。 –

+0

我的感覺是'1&2'比簡單的'>&2'稍微含糊不清。沒有? (我的意思是,它更清楚地說明了看劇本的人發生了什麼事情,bash顯然不在意。) –

+0

當然,這很好 - 你只是不需要它。 –

1

典型的成語是:

echo foo >&2   # you don't need to specify file descriptor 1 
echo foo > /dev/stderr # more explicit, but wordier and less portable 
2

的問題似乎表明一些混亂。你不想重定向stdout,你只是想讓printf把它的輸出發送到stderr ......但是爲了達到這個目的,你必須使用重定向。

printf命令總是發送正常輸出到它的標準輸出。這就是printf所做的。爲了實現你想要的,你必須讓shell安排stdout臨時指向你想要輸出的地方。注意我暫時說。當你喜歡

$ printf "Hello World!" >&2 

鍵入命令的shell修改爲printf語句的執行期間的標準輸出句柄。然後,shell在繼續下一個命令之前恢復stdout的原始值。事實上,如果你想永久重定向標準輸出,可以使用特殊的命令

$ exec >&2 

外殼已被執行之後此,外殼不再記得標準輸出手柄的原始值。

相關問題