Bash

重定向標準輸出和錯誤時,在沒有 >> 的情況下附加作品

  • January 23, 2015

我有一個文件test.txt,但沒有名為test. 當我嘗試

ls test test.txt > new 2>new

我期待new被覆蓋,因為>>沒有使用。但是在輸出文件中,我附加了兩個內容。為什麼會這樣?

TL;DR bash在寫入任何內容之前打開並截斷所有涉及的文件。stdout並且stderr都被發送到,new因為在開始列印bash時已經截斷了文件(兩次) 。ls

這就是bash準備/處理 I/O 重定向的方式。當您要求將命令重定向(>)到文件時,bash基本上會打開該文件,並在必要時創建它。如果文件已存在,則將其截斷。在您的情況下,這是通過open系統呼叫和一些標誌來完成的:

open("new", O_WRONLY|O_CREAT|O_TRUNC, 0666)

O_CREAT如果文件不存在則創建該文件,如果存在則O_TRUNC截斷該文件。此open系統呼叫是bash重定向初始化的一部分,這意味著當您使用多個重定向操作時,例如在…

$ ls test test.txt > new 2>new

bash首先打開所有相關文件。因此,在執行之前ls,它會打開new兩次,使用相同的標誌:

open("new", O_WRONLY|O_CREAT|O_TRUNC, 0666)
open("new", O_WRONLY|O_CREAT|O_TRUNC, 0666)

這意味著基本上,在執行您的命令時,bash執行以下操作(按此順序):

  1. 作為標準輸出打開new,必要時創建/截斷文件。
  2. 作為標準錯誤打開new,必要時創建/截斷文件。
  3. 執行ls:這會將內容寫入new.

如您所見,在開始之前bash截斷所有涉及的文件。這意味著當使用 , 執行某些東西時,基本上被截斷“兩次”,然後,輸出被重定向到它。您期望的行為需要獨立擷取’s stdout 和 stderr ,並在寫入之前一個接一個地打開它們。基本上:ls``... >new 2>new``new``bash``ls

  1. 開始ls
  2. 當有事情發生時stdout,打開new,截斷它並寫入它。
  3. 當某些事情發生時stderr,再次打開new,截斷它,然後寫入它。

但是,消息可能會交織在一起:重定向的程序很可能會向 寫入一些內容,stdout然後.行為…)stderr``stdout

引用自:https://unix.stackexchange.com/questions/180660