Linux 命令之 cp

简介

cp 命令,主要用来复制文件和目录,同时借助某些选项,还可以实现复制整个目录,以及比对两文件的新旧而予以升级等功能。

语法

1
2
3
4
5
6
7
8
9
10
11
cp [选项] 源文件 目标文件

选项:
-a:相当于 -d、-p、-r 选项的集合;
-d:如果源文件为软链接(对硬链接无效),则复制出的目标文件也为软链接;
-i:询问,如果目标文件已经存在,则会询问是否覆盖;
-l:把目标文件建立为源文件的硬链接文件,而不是复制源文件;
-s:把目标文件建立为源文件的软链接文件,而不是复制源文件;
-p:复制后目标文件保留源文件的属性(包括所有者、所属组、权限和时间);
-r:递归复制,用于复制目录;
-u:若目标文件比源文件有差异,则使用该选项可以更新目标文件,此选项可用于对文件的升级和备用。

需要注意的是,源文件可以有多个,但这种情况下,目标文件必须是目录才可以。

这里的软链接,类似于 Windows 系统中的快捷方式,而硬链接则是透过文件系统的 inode 号产生一个新的文件名。无论是复制软链接还是硬链接,都不是复制源文件。

linux 在同一目录下不能存在同名的文件和文件夹,cp 复制时,会自动判断源文件和目标文件是目录还是文件,有两种情况:

  • 源路径是文件

    • 如果目标路径已存在,判断目标路径是否为目录
      • 如果目标路径是目录,这直接将文件复制到该目录下
      • 如果目标路径是文件,则提示是否覆盖
    • 如果目标路径不存在
      • 复制过去并重命名为目标路径
  • 如果源路径是目录,需要使用参数 -r

    • 如果目标路径已存在,判断目标路径是否为目录
      • 如果目标路径是目录,这直接将源目录复制到该目录下
      • 如果目标路径是文件,则报错 cp: cannot overwrite non-directory ‘test1/1.rar’ with directory 'test'
    • 如果目标路径不存在
      • 直接将文件复制过去,并重命名为目标路径

示例

复制文件

1
2
3
4
5
6
7
8
9
# 把源文件不改名复制到 /tmp/ 目录下(目标路径为目录)
[root@localhost ~]# cp test.txt /tmp/

# 改名复制(目标路径为文件)
[root@localhost ~]# cp test.txt /tmp/test_new.txt

# 如果复制的目标位置已经存在同名的文件,则会提示是否覆盖,因为 cp 命令默认执行的是“cp -i”的别名,例如再执行:
[root@localhost ~]# cp test.txt /tmp/test_new.txt
cp:是否覆盖"/tmp/cangls"?y #目标位置有同名文件,所以会提示是否覆盖

复制目录

1
2
3
4
5
6
7
8
9
10
# 将 test 文件移到 tmp 文件夹下 (tmp文件夹已存在)
[root@localhost ~]# cp -r /home/test /tmp/

# 将 test 文件移到 tmp 文件夹下,并重命名为test_new (tmp文件夹已存在, test_new 不存在)
[root@localhost ~]# cp -r /home/test /tmp/test_new


# 将 test 文件移到 tmp/test.txt, (tmp文件夹已存在, test.txt 是文件)
[root@localhost ~]# cp -r /home/test /tmp/test.txt
cp: cannot overwrite non-directory ‘tmp/test.txt’ with directory ‘test’ # 报错

复制软链接文件

如果源文件不是一个普通文件,而是一个软链接文件,那么是否可以复制软链接的属性呢?我们试试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 建立一个测试软链接文件/tmp/cangls_slink 
[root@localhost ~]# ln -s /root/cangls /tmp/cangls_slink
[root@localhost ~]# ll /tmp/cangls_slink
lrwxrwxrwx 1 root root 12 614 05:53 /tmp/cangls_slink -> /root/cangls

# 复制软链接文件,但是不加"-d"选项
[root@localhost ~]# cp /tmp/cangls_slink /tmp/cangls_t1

# 复制软链接文件,加入"-d"选项
[root@localhost ~]# cp -d /tmp/cangls_slink /tmp/cangls_t2


[root@localhost ~]# ll /tmp/cangls_t1 /tmp/cangls_t2
-rw-r--r-- 1 root root 0 614 05:56 /tmp/cangls_t1 # 会发现不加"-d"选项,实际复制的是软链接的源文件,而不是软链接文件
lrwxrwxrwx 1 root root 12 614 05:56/tmp/cangls_t2-> /root/cangls # 而如果加入了"-d"选项,则会复制软链接文件

这个例子说明,如果在复制软链接文件时不使用 -d 选项,则 cp 命令复制的是源文件,而不是软链接文件;只有加 -d 选项,才会复制软链接文件。注意,-d 选项对硬链接是无效的。

保留源文件属性复制

我们发现,在执行复制命令后,目标文件的时间会变成复制命令的执行时间,而不是源文件的时间。例如:

1
2
3
4
5
6
[root@localhost ~]# cp /var/lib/mlocate/mlocate.db /tmp/  
[root@localhost ~]# ll /var/lib/mlocate/mlocate.db
-rw-r-----1 root slocate2328027 614 02:08/var/lib/mlocate/mlocate.db # 注意源文件的时间和所属组

[root@localhost ~]#ll /tmp/mlocate.db
-rw-r----- 1 root root2328027 614 06:05/tmp/mlocate.db # 由于复制命令由root用户执行,所以目标文件的所属组为了root,而且时间也变成了复制命令的执行时间

而当我们执行备份、曰志备份的时候,这些文件的时间可能是一个重要的参数,这就需执行 -p 选项了。这个选项会保留源文件的属性,包括所有者、所属组和时间。例如:

1
2
3
4
[root@localhost ~]# cp -p /var/lib/mlocate/mlocate.db /tmp/mlocate.db_2  #使用"-p"选项  
[root@localhost ~]# ll /var/lib/mlocate/mlocate.db /tmp/mlocate.db_2
-rw-r----- root slocate 2328027 614 02:08 /tmp/mlocate.db_2
-rw-r----- root slocate 2328027 614 02:08 /var/lib/mlocate/mlocate.db #源文件和目标文件的所有属性都一致,包括时间

-a 选项相当于 -d、-p、-r 选项,当我们使用 -a 选项时,目标文件和源文件的所有属性都一致,包括源文件的所有者,所属组、时间和软链接性。使用 -a 选项来取代 -d、-p、-r 选项更加方便。


Linux 命令之 cp
https://flepeng.github.io/002-Linux-21-命令-Linux-命令之-cp/
作者
Lepeng
发布于
2021年7月5日
许可协议