Bash
作為 for 循環的一部分寫入同一文件會生成一個空文件
我正在編寫一個命令,將一些文本添加到與特定模式匹配的一堆文件中:
for file in $(find . -name "*.txt"); do sed "1s/^/hello/" $file; done
如果我寫入
stdout
或寫入不同的文件(例如"$file.bak"
),一切都會按計劃進行,但是當我嘗試讓命令寫回同一個文件時,文件的內容會被清除:for file in $(find . -name "*.txt");do sed "1s/^/hello/" $file > $file; done
我發現這種行為令人驚訝,有人可以從概念上解釋為什麼會發生這種情況嗎?我在 macOS 上,我已經嘗試過這個
bash
並zsh
達到同樣的效果。(請注意,我知道
sed -i ""
就地寫入,但我想在就地寫入之前將結果通過管道傳輸到不同的命令。)
概念上的驚喜可能在此聲明中
但是當我嘗試讓命令寫回同一個文件時
使用
cmd file > file
它時,它不是cmd
打開要寫回的文件,而是打開外殼本身。shell 看到的第一件事是以> file
寫入模式在位置 0 處打開文件(從而截斷它),然後將 stdout 重定向到該文件。所以此刻cmd
開始讀取file
它已經是空的。或者,更正式一點:
- Shell fork 一個新的程序來
cmd
執行- 新程序(仍在執行的 shell 程式碼)打開
file
以在位置 0 寫入(從而截斷它)- 新程序執行
cmd
,實際上是在目前程序中啟動一個新的二進製文件。cmd
以 stdout 指向執行file
cmd
打開file
閱讀,但此時它已經是空的另一方面,如果您使用
sed -i '1s/^/hello/' file
該文件僅由sed
(技術上在後台創建一個臨時文件)管理。