對子shell中的輸入和父shell中的輸出使用相同的文件名會衝突嗎?
參考我的這個答案,我使用相同的
tmp
文件作為程序替換的輸入,並將輸出寫入tmp
父 shell 中的同一個文件,這是否會在程序替換中讀取和由 shell 寫入時導致任何中斷?根據評論中的討論和我發現的類似文章,似乎不應該衝突,對吧?
grep -xvFf <(cut -d'/' -f1 tmp) ext >> tmp
評論中的相關討論:
這看起來很優雅,但不是
tmp
同時被讀取和寫入嗎?–卡西莫多@Quasímodo 不,child-shell 打開
tmp
只讀模式,並在grep
完成處理後完成重定向,然後 shell 打開tmp
再次寫入(但我仍然不是這方面的專家,無法 100% 確認) – αғsнιη@Quasímodo
strace 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>
重定向只是截斷文件而不影響輸出。)