Linux文件拷贝命令cp
cp
命令,全称为 copy
,可以用来拷贝文件或目录。
语法选项
命令语法很简单,如下所示
1 | cp [OPTION] SOURCE DEST |
SOURCE
指的是源文件,也就是被拷贝的文件或目录,DEST
为目标文件,也就是拷贝后生成的文件或目录。需要注意的是 SOURCE
可以是多个文件或目录。
常用的命令选项,总结如下
-f
:如果目的文件存在,强制直接覆盖,长选项--force
-i
:如果目的文件存在,则进入交互模式,需要在提示符后输入y
确认后覆盖-p
:拷贝时保持源文件的属性包括:权限模式、属主属组、时间戳-r
:递归拷贝源目录中所有的内容-l
:拷贝的是硬链接而不是文件的副本,两个文件的inode
是一样的-v
:显示拷贝详情,在脚本中使用该选项非常有用-a
:拷贝生成的文件或目录与源文件属性完全一样-b
:如果目的文件存在,则先备份再拷贝-s
:拷贝的是软连接而不是文件的副本-u
:如果目的文件存在,只有当源文件比目的文件更新时才拷贝-P
:如果源文件是软连接,拷贝的是软连接文件本身,而不是软连接指向的文件-n
:如果目的文件存在,不要覆盖文件
上边只罗列了 cp
命令中常用的选项,基本可以满足大部分日常工作需求。如上述选项不能够满足需求,可以自己 man cp
查看手册详情。
用法示例
接下来,总结一些 cp
命令常见的使用方法
1. 文件拷贝。如果要拷贝到别的目录,目的文件需要指定目录
1 | $ cp foo.txt bar.txt |
2. 目录拷贝。如果是目录需要指定 -r
选项,可以将整个目录所有的内容都拷贝过去
1 | $ cp -r conf conf.bak |
如果希望拷贝时继承源目录的属性,同时指定 -p
选项即可
3. 拷贝已存在的文件
通过 cp
拷贝文件,如果目的文件已存在,默认会直接覆盖目的文件。如果希望不覆盖,可以指定 -n
选项;指定 -i
选项进入交互界面,用户可以输入 y
或 n
来选择是否覆盖。
1 | # 不覆盖 |
需要注意的是,有些系统为了安全起见,默认会为 cp
命令设置 alias
别名,增加 -i
选项,如果目的文件存在,默认就会进入提示界面。大部分情况下,在脚本中要用户进行交互是很不方便的,可以通过指定 -f
选项,或者使用命令的全路径 /bin/cp
这样的方式进行解决。
4. 拷贝已存在的目录
如果拷贝的是目录,且目标目录已存在,会发生什么呢?我们先来做个简单实验,希望将 foo
目录拷贝为 bar
,如果存在完全覆盖
1 | $ cp -rp foo bar |
结果是将 foo
目录拷贝到 bar
目录下,而不是在直接覆盖 bar
目录。通过查找资料和多次实验,发现通过 cp
命令本身无法做到,可以使用如下方式,虽然不优雅但能解决问题
1 | $ /bin/rm -r bar && /bin/cp -r foo bar |
5. 拷贝多个文件或目录
上边的实验代码拷贝的都是单个目录或文件,其实 cp
可以同时拷贝多个文件和目录
1 | $ cp -rp -v a.txt b.txt foo /root/ |
上述命令表示将 a.txt
文件、b.txt
文件、foo
目录拷贝到 /root 目录下。可以看到命令执行时,会显示每个文件拷贝的详情,这是由于添加了 -v
选项,在拷贝多个文件时非常有用。
6. 拷贝硬链接而不是文件副本
1 | $ cp -l foo.txt foo2.txt |
上述命令指定 -l
选项,表示为 foo.txt
文件创建了硬链接文件 foo2.txt
,而不是文件副本,相当于为 foo.txt
设置一个别名
7. 拷贝软连接文件
如果源文件时软连接,默认 cp
会拷贝软连接指向的目标文件。如果我们希望只是拷贝软连接文件本身,而不是所指向的文件,可以使用 -P
选项
1 | $ ln -s foo.txt foo.link.txt |
可以看到 bar.txt
也是软连接文件,指向 foo.txt
文件
8. 拷贝较新的文件
当我们在拷贝大文件时,只希望在文件有更新时再去拷贝和覆盖旧文件,这样可以避免无谓的磁盘拷贝,通过指定 -u
选型即可
1 | $ cp -u bignew.txt bigfile.txt |
如果 bigfile.txt
文件不存在,则一定会发生拷贝;如果 bigfile.txt
存在且比 bignew.txt
文件新,则不会拷贝。
-u 拷贝大文件时,如果没有变化,就不要拷贝了