本篇介紹如何在 Linux 系統下使用 cp 指令複製檔案或目錄,並提供常見的使用範例。

在 Linux 系統之中若要進行檔案或目錄的複製,可以使用 cp 指令,而除了簡單的複製檔案之外,此指令也具有額外的建立連結、自動備份等附加功能,以下是 cp 指令的使用方式介紹。

複製檔案

若要將 source.txt 檔案複製一份到 dest.txt,可以執行:

# 將 source.txt 複製到 dest.txt
cp source.txt dest.txt

若要將 source.txt 複製到其他目錄之下,可以指定絕對路徑:

# 將 source.txt 複製到 /path/to/dest.txt
cp source.txt /path/to/dest.txt

如果要將檔案複製到其他目錄,保持原來的檔案名稱,可以僅指定目的目錄即可,也就是說以下兩種寫法是等效的:

# 將 source.txt 複製到 /path/to/source.txt
cp source.txt /path/to/source.txt

# 將 source.txt 複製到 /path/to/source.txt
cp source.txt /path/to/

亦可將多個檔案一起複製到目的目錄:

# 將 source1.txt、source2.txt、source3.txt 複製到 /path/to 目錄中
cp source1.txt source2.txt source3.txt /path/to/

複製目錄

如果要複製整個目錄以及該目錄下的所有子目錄與檔案,可以加上 -r 參數(或是 -R--recursive 參數亦可),以遞迴的方式進行複製:

# 將 myfolder 目錄複製到 /path/to/ 路徑下
cp -r myfolder /path/to/

強制覆蓋檔案

若遇到目的檔案已存在的情況,cp 指令預設會覆蓋既有的檔案內容,但是如果目的檔案檔案無法寫入(例如檔案權限設定為唯讀),就會無法進行複製的動作。

如果希望 cp 指令在無法寫入目的檔案時,嘗試刪除目的檔案,再重新複製一份新的檔案,可以加上 -f--force 參數:

# 強制複製檔案
cp -f source.txt dest.txt

如果希望 cp 指令在每次複製檔案前都先刪除目的檔案,再進行檔案的複製,則可加上 --remove-destination 參數:

# 先刪除目的檔案,再進行複製
cp --remove-destination source.txt dest.txt

不要覆蓋既有檔案

如果希望 cp 指令遇到目的檔案已經存在的狀況,不要覆蓋既有的檔案,可以加上 -n--no-clobber 參數:

# 不要覆蓋既有檔案
cp -n source.txt dest.txt

另一種方式是加上 -i--interactive 參數,讓 cp 在覆蓋檔案之前,先詢問使用者,經確認之後再進行覆寫:

# 經確認後再覆寫檔案
cp -i source.txt dest.txt

自動備份檔案

若希望 cp 指令在覆蓋檔案時,可以將舊檔案自動備份起來,可以加上 -b--backup 參數:

# 自動備份檔案
cp -b source.txt dest.txt

cp 指令預設會將原始檔案名稱加上 ~ 這個後綴,作為備份檔案名稱(例如 dest.txt 就會備份至 dest.txt~),若要自行指定備份檔名後綴,可以用 -S--suffix 參數來更改,例如改用 .bak 作為備份檔案名稱的後綴:

# 指定備份檔名後綴
cp -b -S .bak source.txt dest.txt

這樣 dest.txt 就會被備份至 dest.txt.bak

保留檔案屬性

若希望 cp 在複製檔案時,可以連同檔案屬性一起複製,可以加上 -p--preserve 參數:

# 保留檔案屬性
cp -p source.txt dest.txt

加上 -p--preserve 參數預設會保留權限(mode)、擁有者(ownership)、時間戳記(timestamps),若希望更改保留的屬性種類,可以使用 --preserve 參數來指定,其餘可用的選項有 SELinux contexts(context)、連結(links)、延伸屬性(xattr)、所有屬性(all),例如:

# 指定保留的檔案屬性
cp --preserve=mode,ownership,timestamps,xattr source.txt dest.txt

若只要複製檔案的屬性,而不要複製檔案本身的資料,可以加上 --attributes-only 參數:

# 只複製檔案屬性
cp --attributes-only source.txt dest.txt

關於各屬性種類的說明,可以參考 File permissions and attributes

連結檔解析

假設我們建立一個連結檔 link.txt 指向 source.txt

# 建立連結檔
ln -s source.txt link.txt

如果希望 cp 指令在複製連結檔案時,能夠解析連結檔所指向的實際檔案,複製那一個實際的目標檔案,可以加上 -L--dereference 參數:

# 複製檔案(解析連結)
cp -L link.txt dest.txt

由於 link.txt 是指向 source.txt 的連結檔,所以這裡的 dest.txt 實際上就是從 source.txt 所複製出來了。

若希望 cp 指令在複製連結檔案時,不要進行連結的解析,僅將連結檔直接複製,則可改用 -P--no-dereference 參數:

# 複製檔案(保留連結)
cp -P link.txt link2.txt

此處所複製出來的 link2.txt 就僅僅是一個指向 source.txt 的連結檔案。

以軟連結、硬連結複製檔案

cp 指令若加上 -s--symbolic-link 參數,可以用軟連結(symbolic link)的方式建立檔案,也就是等同於使用 ln -s 指令來建立連結:

# 以軟連結複製檔案
cp -s source.txt link.txt

這樣建立的 link.txt 檔案就是一個指向 source.txt 的連結檔。

若要以硬連結複製檔案,可以加上 -l--link 參數:

# 以硬連結複製檔案
cp -l source.txt dest.txt

這裡 dest.txt 的 inode 會與 source.txt 相同。

保留來源目錄結構

若要保留來源檔案的目錄結構,可以加上 --parents 參數:

# 保留來源目錄結構
cp --parents path/to/source.txt myfolder/

這樣就會把 path/to/source.txt 複製到 myfolder/path/to/source.txt

僅更新檔案

cp 指令若加上 -u--update 參數,就會自動檢查來源檔案與目的檔案的修改時間,如果來源檔案比目的檔案更新,才會更新目的檔案,否則就不做任何動作:

# 僅更新檔案
cp -u source.txt dest.txt

參考資料