linux cp命令详解


cp为copy的缩写,cp命令主要用来复制文件和目录,常用的命令格式如下所示:

              peter@initroot:~$ cp [-adfilprsu] 来源文件(source) 目标文件(destination)
              peter@initroot:~$ cp [options] source1 source2 source3 .... directory
              选项与参数:
              -a :相当于 -dr --preserve=all 的意思,至于 dr 请参考下列说明;(常用)
              -d :若源文件为链接文件(link file),cp默认复制链接文件指向的文件。加上-d选项则复制链接文件,而非链接文件指向的文件;
              -f :f为force的缩写,即强制复制。若目标文件已经存在则将目标文件删除后再复制;
              -i :互动模式,若目标文件(destination)已经存在时,在复制之前会先询问用户是否执行覆盖操作,为常用选项;
              -l :建立文件的硬链接(hard link),而非复制文件本身;
              -p :连同文件的属性(权限、用户、时间)一起复制过去,而非使用默认属性,此选项经常用来备份重要文件;
              -r :递归选项,用于目录的复制,为常用选项;
              -s :建立文件的符号链接(symbolic link),即软连接,相当于windows下的快捷方式;
              -u :destination比source旧才更新destination,或destination不存在的情况下才复制。
              --preserve=all :除了复制-p的权限属性外,还复制SELinux的属性, links, xattr等也复制了。
            
如果cp命令后面的来源文件参数有两个以上,那么最后一个文件参数必须是目录。 通过以上选项我们发现,cp命令不仅用于复制文件和目录,-l和-s选项还可以用来为文件建立链接, -u选项可以比较两个文件的新旧并更新旧文件。看来cp命令是非常重要的了。
我们切换到root身份,并将家目录下的.bashrc文件拷贝到/tmp目录下,复制后的文件名为bashrc:
              peter@initroot:~$ su -
              Password: 
              root@initroot:~# cp .bashrc /tmp/bashrc
            
此时/tmp目录下已经存在一个bashrc文件了,我们加上-i选项再次执行刚才的命令:
              root@initroot:~$ cp -i .bashrc /tmp/bashrc
              cp: overwrite '/tmp/bashrc'? n
              root@initroot:~$ 
            
因为/tmp目录下已经存在一个bashrc文件了,加上-i选项后,cp会询问我们是否要覆盖掉已经存在的文件, 可以按下n或者y来确认是否要执行覆盖,n是no,y是yes。 这个选项非常有帮助,可以防止用户误操作,所以在拷贝一个文件的时候,最后能加上-i选项。
我们现在切换到/tmp目录下,并将/var/log/wtmp文件复制到/tmp目录下:
              root@initroot:~$ cd /tmp
              root@initroot:/tmp$ cp /var/log/wtmp .
            
注意上面命令中.的含义,我们之前已经讲过了,.表示当前目录。 然后通过ls命令查看复制前后的文件:
              root@initroot:/tmp# ls -l /var/log/wtmp wtmp
              -rw-rw-r-- 1 root utmp 33792 Jan  7 18:23 /var/log/wtmp
              -rw-r--r-- 1 root root 33792 Jan  7 22:07 wtmp
            
我们发现复制后的wtmp文件权限属性发生了改变,文件拥有者和所属用户组都变成了root,文件的权限变成了默认文件权限-rw-r--r--。 文件的时间也发生了改变,这个时间就是我们刚刚执行命令的时刻。 这个其实很好理解,因为cp命令假设执行cp命令的用户希望复制后的文件变成自己的。 我们当前登录用户是root,cp命令是由root用户执行的,所以文件拥有者和所属用户组就自然而然变成root了。 而复制后的文件相当于创建了一个新文件,所以就会以默认权限-rw-r--r--作为复制后文件的权限,而文件的时间就是创建新文件的时间了。 注意复制文件之前,需要对该文件具备读r权限。
如果想将文件的所有属性都一起复制过来,不做任何更改,那么需要加上-a或者-p选项:
              root@initroot:/tmp$ cp -a /var/log/wtmp wtmp_bak
              root@initroot:/tmp# ls -l /var/log/wtmp wtmp wtmp_bak
              -rw-rw-r-- 1 root utmp 33792 Jan  7 18:23 /var/log/wtmp
              -rw-r--r-- 1 root root 33792 Jan  7 22:07 wtmp
              -rw-rw-r-- 1 root utmp 33792 Jan  7 18:23 wtmp_bak
            
这样wtmp_bak文件就和原来文件的属性一模一样了。
我们在复制备份一些系统重要文件的时候,比如/etc/shadow文件,因为cp命令默认会改变文件的属性信息,所以在用cp命令复制文件之前,最好能够加上-a或者-p选项, 这样文件的属性信息就可以完整的保留复制过来了。 另外我们将文件复制给其他用户的时候,也应该注意文件权限的变化。
将/etc目录下所有文件复制到/tmp目录下:
              root@initroot:/tmp# cp /etc/ /tmp/
              cp: -r not specified; omitting directory '/etc/'
            
现在的命令提示信息都已经很全面了,上面cp命令提示没有指定-r选项,所以忽略/etc目录。也就是说如果要复制目录的话,必须加上-r选项,否则cp就撂挑子不干了。
我们加上-r选项:
              root@initroot:/tmp# cp -r /etc/ /tmp/
            
再次强调如果是为了备份系统文件或者目录,一定要加上-a选项防止cp命令修改文件或者目录的属性。
我们上面复制了一份bashrc文件,现在来为该文件建立链接:
              root@initroot:/tmp# ls -l bashrc
              -rw-r--r-- 1 peter peter 3771 Jan  7 21:49 bashrc
              root@initroot:/tmp# cp -s bashrc bashrc_slink
              root@initroot:/tmp# cp -l bashrc bashrc_hlink
              root@initroot:/tmp# ls -l bashrc*
              -rw-r--r-- 2 root  root 3771 Jan  7 21:49 bashrc
              -rw-r--r-- 2 root  root 3771 Jan  7 21:49 bashrc_hlink
              lrwxrwxrwx 1 root  root    6 Jan  7 22:45 bashrc_slink -> bashrc
            
我们发现bashrc文件的链接数由原来的1变成了2,bashrc_hlink文件和bashrc文件的属性一模一样。 bashrc_slink文件为指向bashrc文件的软连接,相当于windows系统下的快捷方式。 -s和-l选项都是用来建立文件的链接,但是两种链接有很大的区别,-s是建立文件的符号连接(symbolic link),也叫软连接,也叫快捷方式。而是-l选项是建立文件的硬链接(hard link)。 关于硬链接和软件链接的概念我们下一章节讲解: linux磁盘与文件系统管理
-u选项只有在源文件比目标文件新的时候才会复制,再用来备份文件的时候经常会用到这个选项:
              [root@root /tmp]# cp -u ~/.bashrc /tmp/bashrc
            
将符号链接文件bashrc_slink复制到bashrc_slink_nd和bashrc_slink_d文件, 复制为bashrc_slink_nd文件时不指定-d选项,复制为bashrc_slink_d文件是指定-d选项:
              root@initroot:/tmp# cp bashrc_slink bashrc_slink_nd
              root@initroot:/tmp# cp -d bashrc_slink bashrc_slink_d
              root@initroot:/tmp# ls -l bashrc*
              -rw-r--r-- 2 root  root  3771 Jan  7 21:49 bashrc
              -rw-r--r-- 2 root  root  3771 Jan  7 21:49 bashrc_hlink
              lrwxrwxrwx 1 root  root     6 Jan  7 22:45 bashrc_slink -> bashrc
              lrwxrwxrwx 1 root  root     6 Jan  7 23:06 bashrc_slink_d -> bashrc
              -rw-r--r-- 1 root  root  3771 Jan  7 23:06 bashrc_slink_nd
            
默认情况下,如果源文件是符号链接文件,cp复制的是符号文件所链接的实际文件。 如果指定-d选项,那么cp命令复制的就是符号链接文件,而不是符号链接所指向的实际文件。
cp命令可以同时指定多个参数文件,这些参数文件都作为源文件同时拷贝到目标目录中,最后一个目标文件必须是目录:
              root@initroot:/tmp# cp ~/.bashrc ~/.bash_history /tmp
            
我们现在退出root,恢复到peter用户身份,然后指定-a选项再次复制/var/log/wtmp文件到/tmp目录下,复制后的文件名为peter_wtmp:
            root@initroot:/tmp# exit
            logout
            peter@initroot:/tmp$ cp -a /var/log/wtmp /tmp/peter_wtmp
            peter@initroot:/tmp$ ls -l /var/log/wtmp /tmp/peter_wtmp
            -rw-rw-r-- 1 peter peter 33792 Jan  7 18:23 /tmp/peter_wtmp
            -rw-rw-r-- 1 root  utmp  33792 Jan  7 18:23 /var/log/wtmp
            -rw-rw-r-- 1 root  utmp  33792 Jan  7 18:23 wtmp_bak
            
通过与root的对比我们发现,普通用户peter用-a选项复制文件后,复制后的文件所有者和文件所属用户组都变成了peter,文件权限没有发生改变。 说明普通用户即使用-a选项也是无法完全复制源文件的所有属性信息的。
由上面的操作,我们可以看出在执行cp命令的时候还是有很多需要注意和考虑的地方:
1.是否需要保留源文件的属性信息;
2.源文件是否为链接文件(symbolic link file);
3.源文件是否为特殊的文件,例如FIFO, socket文件等;
4.源文件是否为目录。

cp命令用于复制文件,可以将一个文件拷贝到另一个文件中,也可以将文件拷贝到目录中,基本用法如下:

              root@initroot:/tmp$ cp [-r] SOURCE DEST
              将test.txt文件拷贝到test_bak.txt文件:
              root@initroot:/tmp$ cp test.txt test_bak.txt
              将test.txt文件分别拷贝到destdir目录下:
              root@initroot:/tmp$ cp test.txt destdir
            
-r选项用于递归拷贝子目录

scp是secure copy的简写,常用于将本地文件复制到远程服务器,或者将远程服务器文件拷贝到本地

命令常用示例:

              root@initroot:/tmp$ scp [-r] local_file remote_username@remote_ip:remote_folder
            
1.将linuxqq.jpg文件以root身份拷贝到139.129.101.69服务器的/root/images目录下:
              root@initroot:/tmp$ scp linuxqq.jpg root@139.129.101.69:/root/images
            
2.将images目录及其子目录下的所有文件以root身份拷贝到139.129.101.69服务器的/root/images目录下:
              root@initroot:/tmp$ scp -r images root@139.129.101.69:/root/images
            
3.将139.129.101.69服务器的/root/images/linuxqq.jpg文件以root身份拷贝到当前目录下:
              root@initroot:/tmp$ scp . root@139.129.101.69:/root/images/linuxqq.jpg
            

scp 是通过ssh协议传输数据,如果是想传输一个很大的数据,这几天我就遇到过,一个tar包,400G左右,通过scp拷贝时, 有可能遇到服务器断电什么的悲剧问题,那么类似scp拷贝的另一个命令 rsync就可以实现意外中断后,下次继续传,命令如下:
rsync -P --rsh=ssh home.tar 192.168.205.34:/home/home.tar
-P: 是包含了 “–partial –progress”, 部分传送和显示进度
-rsh=ssh 表示使用ssh协议传送数据
如果不想每次都使用 rsync -P rsh=ssh 之类的,可以写成alias scpr="rsync -P --rsh=ssh"
那么下次就可以直接使用 scpr home.tar 192.168.205.34:/home/home.tar 来拷贝数据了。
在传输过程中,目标文件会以.home.tar.xxxx文件也隐藏,可以用la -a来显示出来。如果scpr中断了,那么该文件会变成用户指定的目标文件"home.tar",下次传的时候又会改成.home.tar.xxxx文件。
执行rsync过程中,我们肯定希望把这个job放入后台执行,而不因为secureCRT类似的窗口中断受影响,那么在执行了 rsync -P --rsh=ssh home.tar 192.168.205.34:/home/home.tar, 再输出密码后,可以用ctrl+z 来中断,再使用bg命令让它在后台执行

initroot编辑整理,转载请注明www.initroot.com

100次点赞 100次阅读