在 Linux 中複製文件

2019-08-23 05:39:00

了解在 Linux 中多種複製文件的方式以及各自的優點。

在辦公室裡影印文件過去需要專門的員工與機器。如今,複製是電腦使用者無需多加思考的任務。在電腦裡複製資料是如此微不足道的事,以致於你還沒有意識到複製就發生了,例如當拖動文件到外部硬碟的時候。

數位實體複製起來十分簡單已是一個不爭的事實,以致於大部分現代電腦使用者從未考慮過其它的複製他們工作的方式。無論如何,在 Linux 中複製文件仍有幾種不同的方式。每種方法取決於你的目的不同而都有其獨到之處。

以下是一系列在 Linux、BSD 及 Mac 上複製檔案的方式。

在 GUI 中複製

如大多數作業系統一樣,如果你想的話,你可以完全用 GUI 來管理檔案。

拖拽放下

最淺顯的複製檔案的方式可能就是你以前在電腦中複製檔案的方式:拖拽並放下。在大多數 Linux 桌面上,從一個本地資料夾拖拽放下到另一個本地資料夾是移動檔案的預設方式,你可以通過在拖拽檔案開始後按住 Ctrl 來改變這個行為。

你的滑鼠指標可能會有一個指示,例如一個加號以顯示你在複製模式。

複製一個文件

注意如果檔案是放在遠端系統上的,不管它是一個 Web 伺服器還是在你自己網路裡用檔案共用協定存取的另一台電腦,預設動作經常是複製而不是移動檔案。

右擊

如果你覺得在你的桌面拖拽文件不夠精準或者有點笨拙,或者這麼做會讓你的手離開鍵盤太久,你可以經常使用右鍵選單來複製檔案。這取決於你所用的檔案管理器,但通常來說,右鍵彈出的關聯選單會包括常見的操作。

關聯選單的“複製”動作將你的檔案路徑(即檔案在系統的位置)儲存在你的剪下板中,這樣你可以將你的檔案貼上到別處:(LCTT 譯註:此處及下面的描述不確切,這裡並非複製的檔案路徑的“字串”,而是複製了代表檔案實體的物件/指標)

從右鍵菜單複製文件

在這種情況下,你並沒有將檔案的內容複製到你的剪下版上。取而代之的是你複製了檔案路徑。當你貼上時,你的檔案管理器會檢視剪貼簿上的路徑並執行複制命令,將相應路徑上的檔案貼上到你準備複製到的路徑。

用命令列複製

雖然 GUI 通常是相對熟悉的複製檔案方式,用終端複製卻更有效率。

cp

在終端上等同於在桌面上複製和貼上檔案的最顯而易見的方式就是 cp 命令。這個命令可以複製檔案和目錄,也相對直接。它使用熟悉的來源目的(必須以這樣的順序)句法,因此複製一個名為 example.txt 的檔案到你的 Documents 目錄就像這樣:

$ cp example.txt ~/Documents

就像當你拖拽檔案放在資料夾裡一樣,這個動作並不會將 Documents 替換為 example.txt。取而代之的是,cp 察覺到 Documents 是一個資料夾,就將 example.txt 的副本放進去。

你同樣可以便捷有效地重新命名你複製的文件:

$ cp example.txt ~/Documents/example_copy.txt

重要的是,它使得你可以在與原檔案相同的目錄中生成一個副本:

$ cp example.txt example.txtcp: 'example.txt' and 'example.txt' are the same file.$ cp example.txt example_copy.txt

要複製一個目錄,你必須使用 -r 選項(代表 --recursive,遞回)。以這個選項對目錄 nodes 執行 cp 命令,然後會作用到該目錄下的所有檔案。沒有 -r 選項,cp 不會將目錄當成一個可複製的物件:

$ cp notes/ notes-backupcp: -r not specified; omitting directory 'notes/'$ cp -r notes/ notes-backup

cat

cat 命令是最易被誤解的命令,但這只是因為它表現了 系統的極致靈活性。在 cat 可以做到的所有事情中(包括其原意的連線檔案的用途),它也能複製。例如說使用 cat 你可以僅用一個命令就從一個檔案建立兩個副本。你用 cp 無法做到這一點。

使用 cat 複製文件要注意的是系統解釋該行為的方式。當你使用 cp 複製檔案時,該檔案的屬性跟著檔案一起被複製,這意味著副本的許可權和原件一樣。

$ ls -l -G -g-rw-r--r--. 1 57368 Jul 25 23:57  foo.jpg$ cp foo.jpg bar.jpg-rw-r--r--. 1 57368 Jul 29 13:37  bar.jpg-rw-r--r--. 1 57368 Jul 25 23:57  foo.jpg

然而用 cat 將一個檔案的內容讀取至另一個檔案是讓系統建立了一個新檔案。這些新檔案取決於你的預設 umask 設定。要了解 umask 更多的知識,請閱讀 Alex Juarez 講述 umask 以及許可權概覽的文章。

執行 unmask 獲取當前設定:

$ umask0002

這個設定代表在該處新建立的文件被給予 664rw-rw-r--)許可權,因為該 unmask 設定的前幾位數位沒有遮掩任何許可權(而且執行位不是檔案建立的預設位),並且寫入許可權被最終位所遮蔽。

當你使用 cat 複製時,實際上你並沒有真正複製檔案。你使用 cat 讀取檔案內容並將輸出重定向到了一個新檔案:

$ cat foo.jpg > baz.jpg$ ls -l -G -g-rw-r--r--. 1 57368 Jul 29 13:37  bar.jpg-rw-rw-r--. 1 57368 Jul 29 13:42  baz.jpg-rw-r--r--. 1 57368 Jul 25 23:57  foo.jpg

如你所見,cat 應用系統預設的 umask 設定建立了一個全新的檔案。

最後,當你只是想複製一個檔案時,這些手段無關緊要。但如果你想複製檔案並保持預設許可權時,你可以用一個命令 cat 完成一切。

rsync

有著著名的同步源和目的檔案的能力,rsync 命令是一個複製檔案的多才多藝的工具。最為簡單的,rsync 可以類似於 cp 命令一樣使用。

$ rsync example.txt example_copy.txt$ lsexample.txt    example_copy.txt

這個命令真正的威力藏在其能夠不做不必要的複製的能力裡。如果你使用 rsync 來將檔案複製進目錄裡,且其已經存在在該目錄裡,那麼 rsync 不會做複製操作。在本地這個差別不是很大,但如果你將海量資料複製到遠端伺服器,這個特性的意義就完全不一樣了。

甚至在本地中,真正不一樣的地方在於它可以分辨具有相同名字但擁有不同資料的檔案。如果你曾發現你面對著同一個目錄的兩個相同副本時,rsync 可以將它們同步至一個包含每一個最新修改的目錄。這種設定在尚未發現版本控制威力的業界十分常見,同時也作為需要從一個可信來源複製的備份方案。

你可以通過建立兩個資料夾有意識地模擬這種情況,一個叫做 example 另一個叫做 example_dupe

$ mkdir example example_dupe

在第一個資料夾裡建立檔案:

$ echo "one" > example/foo.txt

rsync 同步兩個目錄。這種做法最常見的選項是 -a(代表 “archive”,可以保證符號連結和其它特殊檔案保留下來)和 -v(代表 “verbose”,向你提供當前命令的進度反饋):

$ rsync -av example/ example_dupe/

兩個目錄現在包含同樣的資訊:

$ cat example/foo.txtone$ cat example_dupe/foo.txtone

如果你當作源分支的檔案發生改變,目的檔案也會隨之跟新:

$ echo "two" >> example/foo.txt$ rsync -av example/  example_dupe/$ cat example_dupe/foo.txtonetwo

注意 rsync 命令是用來複製資料的,而不是充當版本管理系統的。例如假設有一個目的檔案比原始檔多了改變,那個檔案仍將被覆蓋,因為 rsync 比較檔案的分歧並假設目的檔案總是應該映象為原始檔:

$ echo "You will never see this note again" > example_dupe/foo.txt$ rsync -av example/  example_dupe/$ cat example_dupe/foo.txtonetwo

如果沒有改變,那麼就不會有複製動作發生。

rsync 命令有許多 cp 沒有的選項,例如設定目標許可權、排除檔案、刪除沒有在兩個目錄中出現的過時檔案,以及更多。可以使用 rsync 作為 cp 的強力替代或者有效補充。

許多複製的方式

在 POSIX 系統中有許多能夠達成同樣目的的方式,因此開源的靈活性名副其實。我忘了哪個複製資料的有效方式嗎?在評論區分享你的複製神技。