本文將揭示一些與使用相關的非顯而易見的事情 cp
複製時,以及允許您正確複製大量文件而不會跳過或崩潰的方法。
假設我們需要將 /source 資料夾中的所有內容複製到 /target 資料夾。
第一個想到的是:
cp /source/* /target
讓我們立即將此命令更正為:
cp -a /source/* /target
關鍵 -a
將會新增所有屬性、權限的複製並新增遞歸。當不需要精確複製權利時,密鑰就足夠了 -r
.
複製後,我們會發現並非所有文件都被複製了 - 以點開頭的文件,例如:
.profile
.local
.mc
等等。
為什麼會發生這種情況?
因為通配符是由 shell 處理的(bash
在典型情況下)。預設情況下,bash 將忽略所有以點開頭的文件,因為它將它們視為隱藏文件。為了避免這種行為,我們必須改變行為 bash
使用命令:
shopt -s dotglob
為了確保此行為變更在重新啟動後仍然存在,您可以使用此命令在資料夾中建立一個通配符.sh 檔案 /etc/profile.d
(也許您的發行版有不同的資料夾)。
如果來源目錄中沒有文件,那麼 shell 將無法取代星號的任何內容,並且複製也會失敗並出現錯誤。針對這種情況有一些選擇 failglob
и nullglob
。我們需要設定 failglob
,這將阻止命令被執行。 nullglob
將不起作用,因為它將未找到匹配項的帶有通配符的字串轉換為空字串(零長度),這對於 cp
會導致錯誤。
但是,如果資料夾中有數千個或更多文件,則應完全放棄通配符方法。事實是 bash
將通配符擴展為很長的命令列,例如:
cp -a /souce/a /source/b /source/c …… /target
命令列的長度是有限制的,我們可以使用以下命令來找出:
getconf ARG_MAX
讓我們取得命令行的最大長度(以位元組為單位):
2097152
Или:
xargs --show-limits
我們得到類似的東西:
….
Maximum length of command we could actually use: 2089314
….
因此,我們完全不用通配符。
我們就這樣寫吧
cp -a /source /target
在這裡我們面臨行為的模糊性 cp
。如果 /target 資料夾不存在,那麼我們將得到我們需要的內容。
但是,如果目標資料夾存在,則檔案將複製到 /target/source 資料夾。
我們不能總是提前刪除 /target 資料夾,因為它可能包含我們需要的文件,而我們的目標是,例如,用 /source 中的文件補充 /target 中的文件。
如果來源資料夾和目標資料夾命名相同,例如,我們從 /source 複製到 /home/source,那麼我們可以使用以下命令:
cp -a /source /home
複製後,/home/source 中的文件將被 /source 中的文件補充。
這是一個邏輯問題:如果資料夾名稱相同,我們可以在目標目錄中新增文件,但如果它們不同,則來源資料夾將放置在目標目錄中。如何使用 cp 不使用通配符將檔案從 /source 複製到 /target?
為了解決這個有害的限制,我們使用了一個非顯而易見的解決方案:
cp -a /source/. /target
熟悉DOS和Linux的人都已經明白了:每個資料夾裡面有2個不可見的資料夾「.」。和“..”,它們是指向當前目錄和更高目錄的偽資料夾連結。
- 複印時
cp
檢查是否存在並嘗試創建/target/。 - 這樣的目錄是存在的,它是/target
- /source 中的檔案已正確複製到 /target。
所以,把它掛在你記憶或牆上的一個大膽的框架中:
cp -a /source/. /target
該命令的行為很清楚。無論您是否擁有一百萬個文件或根本沒有文件,一切都將毫無錯誤地運行。
發現
如果您需要複製 所有 檔案從一個資料夾到另一個資料夾,我們不使用通配符,最好使用通配符 cp
與來源資料夾末端的句點組合。這將複製所有文件,包括隱藏文件,並且不會因數百萬個文件或根本沒有文件而失敗。
後記
cp -a -T /source /target
cp -aT /source /target
注意:字母大小寫 T
具有意義。如果你把它混合起來,你會得到完全的垃圾:複製方向會改變。
謝謝:
聚苯乙烯 請透過私人訊息發送您發現的任何錯誤。我為此增加我的業力。
來源: www.habr.com