Bash

對子shell中的輸入和父shell中的輸出使用相同的文件名會衝突嗎?

  • November 16, 2020

參考我的這個答案,我使用相同的tmp文件作為程序替換的輸入,並將輸出寫入tmp父 shell 中的同一個文件,這是否會在程序替換中讀取和由 shell 寫入時導致任何中斷?

根據評論中的討論和我發現的類似文章,似乎不應該衝突,對吧?

grep -xvFf <(cut -d'/' -f1 tmp) ext >> tmp

評論中的相關討論:

這看起來很優雅,但不是tmp同時被讀取和寫入嗎?–卡西莫多

@Quasímodo 不,child-shell 打開tmp只讀模式,並在grep完成處理後完成重定向,然後 shell 打開tmp再次寫入(但我仍然不是這方面的專家,無法 100% 確認) – αғsнιη

@Quasímodostrace grep … 顯示它由 grep 打開並在完成後關閉,因此在 grep done shell 之後將輸出寫入tmp,這樣就不會同時中斷 - αғsнιη

取決於你在做什麼。

對於grep -f patterns,在開始讀取實際數據文件之前,grep幾乎必須先讀取文件。patterns否則它無法知道第一行是否匹配。所以在這裡,你是安全的。

當然,如果您使用截斷重定向到文件,它很可能在程序替換中的命令讀取它之前被截斷。但見下文。


通常,在附加模式下重定向輸出時,我會擔心將輸出循環回輸入。嘗試使用 GNU grep,它足夠聰明地警告這一點:

$ seq 99999 > foo.txt
$ grep ^1 foo.txt >> foo.txt 
grep: input file ‘foo.txt’ is also the output

但是如果我們用程序替換來欺騙它,它會起作用,並且部分數據會被重複處理:

$ grep ^1 <(cat foo.txt) >> foo.txt
$ grep -Fx 1933 foo.txt
1933
1933
1933
1933

當然應該只有兩個副本1933。你的旅費可能會改變。


對於截斷重定向,我在 Linux 上使用以下內容進行了測試:

echo moi > hello.txt
cat <(cat hello.txt) > hello.txt >&2;

在這裡,如果重定向到hello.txt是在內貓執行之前處理的,結果將是沒有輸出。另一方面,如果cat程序內替換首先執行,它可能會在文件被截斷之前讀取文件。循環幾次:

for x in {1..999}; do echo moi > hello.txt; cat <(cat hello.txt) 3> hello.txt; done

如果它處於空閒狀態,則不會在我的系統上提供任何輸出,但如果同時執行一個簡單的busyloop,則會輸出moi幾到幾十次。(3>重定向只是截斷文件而不影響輸出。)

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