2014-09-30 72 views
1

我試圖將許可證連接到我的內置源的頂部。我使用GNU Make。在我的一個規則中,我有:從Unix重定向文件到自己的無限循環cat

cat src/license.txt build/3d-tags.js > build/3d-tags.js 

但是,這似乎是造成無限循環。當我殺死cat命令時,我發現build/3d-tags只是src/license.txt的內容一遍又一遍?這是怎麼回事?我會懷疑這兩個文件要連接在一起,並將從cat生成的輸出重定向到build/3d-tags.js。我不想追加。我在OSX上,以防這個問題與GNU貓和BSD貓有關。

回答

5

Shell作爲子進程啓動cat。輸出重定向(>)被該子進程作爲其stdout(文件描述符1)繼承。由於子進程在創建時必須繼承文件描述符,因此在啓動子進程之前,shell必須打開輸出文件。

因此,shell會打開build/3d-tags.js進行寫入。此外,由於您沒有追加(>>),因此會截斷該文件。請記住,這發生在cat甚至已啓動之前。此時,由於build/3d-tags.js的原始內容已經消失,並且cat尚未推出,因此無法實現您想要的內容。

然後,當啓動cat時,它會打開其參數中指定的文件。它打開它們的時間和順序並不是非常重要。當然,它可以讓他們閱讀。然後它從src/license.txt讀取並寫入其標準輸出。寫這篇文章去build/3d-tags.js。此時,該文件中的只有內容,因爲它之前被截斷。

cat然後從build/3d-tags.js讀取。它找到剛剛寫在那裏的內容,這是貓先前從src/license.txt讀取的內容。它將該內容寫入文件的末尾。它然後回去並嘗試閱讀更多。當然,它會發現更多需要閱讀的內容,因爲它只是在文件末尾寫入更多數據。它讀取這些剩餘的數據並將其寫入文件。並繼續。

爲了cat工作,因爲你希望(甚至忽略了殼重定向磨滅的build/3d-tags.js內容),它會讀取和保存在內存中build/3d-tags.js的全部內容,不管它有多大,,使它可以在寫入src/license.txt的內容之後編寫它。

可能達到你想要什麼,最好的辦法是這樣的:

cat src/license.txt build/3d-tags.js > build/3d-tags.js.new && mv build/3d-tags.js.new build/3d-tags.js || rm -f build/3d-tags.js.new 

那就是:將兩者連接起來的文件到一個新的文件;如果成功,則將新文件移動到原始文件名(替換原始文件);如果任一步驟失敗,請刪除臨時的「新」文件,以免遺留垃圾。

+0

很酷,感謝您的詳細回覆。我很感激。這是我第一次看到邏輯或在shell腳本中使用(不是我做了很多shell腳本)! – 2014-09-30 05:10:01