Cp

為什麼 cp 被設計為靜默覆蓋現有文件?

  • February 15, 2020

cp使用以下命令進行了測試:

$ ls
first.html   second.html  third.html

$ cat first.html
first

$ cat second.html
second

$ cat third.html
third

然後我複製first.htmlsecond.html

$ cp first.html second.html

$ cat second.html
first

該文件second.html被靜默覆蓋,沒有任何錯誤。但是,如果我通過拖放同名文件在桌面 GUI 中執行此操作,它將first1.html自動添加後綴。這樣可以避免意外覆蓋現有文件。

為什麼不cp遵循這種模式而不是默默地覆蓋文件?

的預設覆蓋行為cp在 POSIX 中指定。

  1. 如果 source_file 是正常文件類型,應採取以下步驟:

3.a. 如果 dest_file 存在並且由上一步寫入,則行為未指定。否則,如果 dest_file 存在,則應採取以下步驟:

3.ai 如果 -i 選項有效,cp 實用程序將向標準錯誤寫入提示並從標準輸入中讀取一行。如果響應不是肯定的,cp 將不再處理 source_file 並繼續處理任何剩餘的文件。

3.a.ii. dest_file 的文件描述符應通過執行等效於 POSIX.1-2017 系統介面卷中定義的 open() 函式的操作獲得,該函式使用 dest_file 作為路徑參數呼叫,並且 O_WRONLY 和 O_TRUNC 的按位包含 OR 作為滯後論點。

3.a.iii. 如果獲取文件描述符的嘗試失敗並且 -f 選項有效,則 cp 應嘗試通過執行與使用 dest_file 呼叫的 POSIX.1-2017 系統介面卷中定義的 unlink() 函式等效的操作來刪除文件作為路徑參數。如果此嘗試成功,cp 將繼續執行步驟 3b。

在編寫 POSIX 規範時,已經存在大量腳本,並內置了預設覆蓋行為的假設。其中許多腳本被設計為無需使用者直接在場即可執行,例如作為 cron 作業或其他後台任務。改變行為會破壞他們。審查和修改它們以添加一個選項以在需要的地方強制覆蓋可能被認為是一項艱鉅的任務,但收益卻微乎其微。

此外,Unix 命令行始終旨在讓有經驗的使用者有效地工作,即使以犧牲初學者的艱難學習曲線為代價。當使用者輸入一個命令時,電腦會期望使用者是認真的,沒有任何事後的猜測;小心使用具有潛在破壞性的命令是使用者的責任。

當最初的 Unix 被開發出來時,與現代電腦相比,這些系統的記憶體和大容量儲存非常少,以至於覆蓋警告和提示可能被視為浪費和不必要的奢侈品。

在編寫 POSIX 標準時,先例已經確立,標準的編寫者非常清楚不破壞向後兼容性的優點。

此外,正如其他人所描述的,任何使用者都可以為自己添加/啟用這些功能,方法是使用 shell 別名,甚至通過建構替換cp命令並修改它們$PATH以在標準系統命令之前找到替換,並以這種方式獲得安全網,如果想要的。

但如果你這樣做,你會發現你正在給自己製造危險。如果cp命令在互動使用時以一種方式執行,而在從腳本呼叫時以另一種方式執行,您可能不記得存在差異。在另一個系統上,您可能最終會變得粗心,因為您已經習慣了自己系統上的警告和提示。

如果腳本中的行為仍然符合 POSIX 標準,那麼您可能會習慣互動式使用中的提示,然後編寫一個執行大量複製的腳本 - 然後發現您再次無意中覆蓋了某些內容。

如果您也在腳本中強制執行提示,那麼當在沒有使用者的上下文(例如後台程序或 cron 作業)中執行時,該命令會做什麼?腳本會掛起、中止還是覆蓋?

掛起或中止意味著本應自動完成的任務將無法完成。不覆蓋有時本身也可能導致問題:例如,它可能導致舊數據被另一個系統處理兩次,而不是被最新數據替換。

命令行的強大功能很大一部分來自這樣一個事實:一旦您知道如何在命令行上執行某項操作,您就會隱含地知道如何通過腳本自動執行此操作。但只有當您以互動方式使用的命令在腳本上下文中呼叫時也完全相同時,這才是正確的。互動使用和腳本使用之間的任何顯著行為差異都會產生一種認知失調,這對高級使用者來說很煩人。

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