Linux

cp -r 的語法差異以及如何克服它們

  • April 6, 2016

假設我們在一個空白目錄中。然後,以下命令:

mkdir dir1
cp -r dir1 dir2

產生兩個(空白)目錄dir1dir2,其中dir2已創建為dir1. 但是,如果我們這樣做:

mkdir dir1
mkdir dir2
cp -r dir1 dir2

然後我們反而發現dir1現在已經被放入了裡面dir2。這意味著完全相同的cp命令的行為會有所不同,具體取決於目標目錄是否存在。如果是這樣,那麼該cp命令的執行方式與此相同:

mkdir dir1
mkdir dir2
cp -r dir1 dir2/.

這對我來說似乎非常違反直覺。我原以為cp -r dir1 dir2(當dir2已經存在時)會刪除現有的dir2(和任何內容)並將其替換為dir1,因為這是cp用於兩個文件時的行為。我知道遞歸副本本身有點不同,因為目錄在 Linux 中的存在方式(以及更廣泛地在類 Unix 系統中),但我正在尋找更多關於為什麼選擇這種行為的解釋。如果您可以向我指出一種確保cp行為符合我預期的方法(例如,無需事先測試並刪除目標目錄),則可以加分。我嘗試了幾個cp選項,但沒有任何運氣。我想我會接受rsync為其他不知道該命令的人在這個問題上發生的解決方案。

如果這種行為不普遍,我在 CentOS 上,使用 bash。

您正在尋找的行為是一種特殊情況

cp -R [-H|-L|-P] [-fip] source_file... target

$$ This $$form 由兩個或多個指定了 -R 選項的操作數表示。cp 實用程序應將根在每個 source_file 的文件層次結構中的每個文件複製到名為如下的目標路徑:

  • 如果目標存在並命名現有目錄,則文件層次結構中每個文件的相應目標路徑的名稱應為目標的串聯,<slash>如果目標不以 a 結尾,則為單個字元<slash>,以及文件相對於文件的路徑名包含 source_file 的目錄。
  • 如果target不存在且指定了兩個操作數,則source_file對應的目標路徑名稱為target;文件層次結構中所有其他文件的相應目標路徑的名稱應是目標、<slash>字元和文件相對於 source_file 的路徑名的串聯。

如果目標不存在並且指定了兩個以上的操作數,這將是一個錯誤……

因此,我會說不可能cp做你想做的事。


由於您的預期行為是“ cp -r dir1 dir2(當dir2已經存在時)將刪除現有dir2(和任何內容)並將其替換為dir1“:

rm -rf dir2 && cp -r dir1 dir2

你甚至不需要檢查是否dir2存在。


解決方案是在源rsync中添加一個尾隨/,以便它不會將dir1自身複製到dir2但將內容複製dir1dir2(它仍會將現有文件保留在 中dir2):

$ tree dir*
dir1
└── test.txt
dir2
└── test2.txt

0 directories, 2 file
$ rsync -a dir1/ dir2
$ tree dir*           
dir1
└── test.txt
dir2
└── test.txt
└── test2.txt

0 directories, 3 files
$ rm -r dir2          
$ rsync -a dir1/ dir2
$ tree dir*           
dir1
└── test.txt
dir2
└── test.txt

0 directories, 2 files

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