2015-12-28 61 views
4

這兩行之間有區別嗎?重定向位置之間的外殼差異

for i in $(seq 1 10); do echo $i - `date`; sleep 1; done >> /tmp/output.txt 

for i in $(seq 1 10); do echo $i - `date` >> /tmp/output.txt ; sleep 1; done 

因爲Robert told me,第一個只讓I/O OP在for循環之外。

但是,如果我輸入tail -f /tmp/output.txt,則表現方式完全相同。

回答

3

如果他們成功,他們也會這樣做。但是,如果因任何原因而失敗,可能會有顯着差異。

第一招:

for ...; do 
    # things 
done >> file 

這將重定向到循環完成後,據稱該文件。但是,只要Bash決定刷新緩衝區,就可能發生這種情況。

想象一下迭代3號後失敗的東西:你不能說出在文件中存儲了什麼。

第二個:

for ...; do 
    # things >> file 
done 

這將重定向到每個迭代的文件。

想象一下在第3次迭代之後某些事情會失敗:您肯定前兩個循環已經正確存儲在文件中。

How to redirect output from an infinite-loop program

如果你的程序使用標準輸出功能(例如puts,從用C stdio.h printf和朋友,cout << …在C++中,print在許多高級語言 )然後,其輸出是 buffered: 字符累積在稱爲緩衝區的內存區域中;當 緩衝區中的數據太多時,緩衝區的內容爲 (它被「刷新」)並且緩衝區變爲空(準備再次填充 )。如果你的程序不會產生太多的輸出,那麼它可能並沒有填充緩衝區。

此外,從the answer you link

配售重定向操作寫50萬線(我的系統上),當循環加倍 性能。

這是有道理的:如果你不得不在每個循環上刷新,那麼只要發現方便,就比Bash刷新花費更多的時間。在每次寫入五行時比寫一行更容易。

+0

謝謝。我怎麼知道Bash什麼時候會決定沖洗緩衝區?例如,我可以強制它每沖洗5/100個循環嗎? – Bast

+0

@以上是一個相當敏感的事情,需要你重寫循環定義本身。從[在bash腳本仍在運行時強制刷新輸出到文件](http://stackoverflow.com/q/1429951/1983854)_bash本身永遠不會將任何輸出寫入日誌文件。相反,它作爲腳本的一部分調用的命令將分別寫入輸出和刷新,只要他們感覺喜歡它。所以你的問題是如何強制bash腳本中的命令刷新,這取決於它們是什麼。 – fedorqui

0

還有另外一個重要的區別沒有提到:>>每次打開文件寫入。這會明顯影響性能。

此外,如果/tmp/output.txt在循環運行時被刪除,echo ... >> /tmp/output.txt將用新內容重新創建文件,而for ... done >> /tmp/output.txt將繼續向同一文件添加數據。

這是重要的要記住,尤其是如果我們正在處理硬鏈接或臨時文件(通常,我們創建它們後不久,我們斷開臨時文件,以避免如果Bash腳本意外退出時有過時的文件)。