每天一個linux命令:拷貝命令家族(cp、scp、rsync) — cp
1. cp功能
cp 命令用來將一個或多個源文件或者目錄複製到目標文件或目錄。
更多精彩請查看:www.zicreate.com
2.命令格式
cp [選項]… [-T] 源 目的
或:cp [選項]… 源… 目錄
或:cp [選項]… -t 目錄 源…
3.主要命令參數
-a:此參數的效果和同時指定”-dpR”參數相同;
-d:當複製符號連接時,把目標文件或目錄也建立爲符號連接,並指向與源文件或目錄連接的原始文件或目錄;
-f:強行復制文件或目錄,不論目標文件或目錄是否已存在;
-i:覆蓋既有文件之前先詢問用戶;
-l:對源文件建立硬連接,而非複製文件;
-p:保留源文件或目錄的屬性;
-R/r:遞歸處理,將指定目錄下的所有文件與子目錄一併處理;
-s:對源文件建立符號連接,而非複製文件;
-u:使用這項參數後只會在源文件的更改時間較目標文件更新時或是名稱相互對應的目標文件並不存在時,才複製文件;
-S:在備份文件時,用指定的後綴“SUFFIX”代替文件的默認後綴;
-b:覆蓋已存在的文件目標前將目標文件備份;
-v:詳細顯示命令執行的操作。
4.使用場景
場景1:文件備份
命令:
備份文件到文件:
$ cp zicreate.txt bak_zicreate.txt
注意:如果不加“-i”參數拷貝,不論bak_zicreate.txt是否存在,命令執行時都不會提示,這種情況下,如果我們拷貝過程中不想覆蓋已經存在的同名文件,可以添加“-i”參數。大部分系統中已經對cp命令進行過處理,拷貝時會提示是否覆蓋,如下:
$ cp joke.txt bak_joke.txt
cp: overwrite ‘bak_joke.txt’? y
$ which cp
alias cp='cp -i'
/usr/bin/cp
如果覺得每次輸入y太繁瑣,可以直接取消別名:
$ unaslias cp (這只是臨時取消cp的別名)
或者用如下方法同樣是取消別名:
$ \cp joke.txt bak_joke.txt
再或者輸入:
$ yes | cp joke.txt bak_joke.txt,使用管道自動輸入yes。
或備份到指定目錄下:
$ cp zicreate.txt ./bak-dir/
或將整個目錄備份到指定目錄下:
$ cp -r dir1 dir3
注意:如果dir3目錄不存在,則會創建目錄dir3,如果dir3目錄存在,則會將文件夾dir1拷貝到目錄dir3裏面。
$ cp -r dir1 dir3
$ ls
dir1 dir2 dir3 joke.txt onlyOne.txt test.txt zicreate.txt
$ ls dir3/
test1.txt
$ cp -r dir1 dir3
$ ls dir3/
dir1 test1.txt
場景2:拷貝時保存源文件的所有權限
這種情況主要應用與拷貝程序可執行程序安裝包、文件系統目錄等特殊場景。
命令:
$cp -rp rootfs/ /mnt/sdcard/
-p參數,可以保持權限、宿主、時間棧,還可能包括link等;還有更簡單的,就是用:
$cp -a rootfs/ /mnt/sdcard/
-a參數,就等於-dpR。
前文的文件夾拷貝都是將文件夾整個拷貝到另一個文件夾內,如果是將文件夾內的全部或部分文件拷貝到已經存在的目標文件夾內,則一般使用通配符,如“*”進行目錄內容拷貝。
$ ls -a ./dir1
. .. .canotsee.txt test1.txt
$ rm dir3/* -rf
$ ls dir3/ -a
. ..
$ cp dir1/* dir3/ -rf
$ ls dir3/ -a
. .. test1.txt
發現沒?使用通配符 “*” 拷貝時,隱藏文件“.canotsee.txt ” 沒有被拷貝到目標文件夾內!
原因是:“*” 通配符定義問題,解決方法很簡單,用“.” 代替“*”就好了(在Linux中,“.” 代表當前目錄,“..” 代表上級目錄)。
最終的完全拷貝命令如下:
$ cp dir1/. dir3/ -rf
關於Shell 通配符的解釋將會推出後續文章,此處只需要記住, ”*” 代表任意字符串,但是位於首字母位置的“.”除外!