看别人的部署脚本,经常见到 cp -v、cp -rv、cp -av 这些写法。v 就一个字母,很多新手直接跳过不看,结果是复制出了问题也发现不了,全被静默吞掉了。
-v 就是 verbose
verbose 意思是「啰嗦」,加上之后 cp 会把每一个被复制的文件名打印出来:
cp -v a.txt b.txt
'a.txt' -> 'b.txt'不加的时候,cp 成功就一声不吭。Linux 的哲学是「没有消息就是好消息」,但脚本里恰恰需要这份消息:出了问题能对照日志找出是哪个文件没复制过去。
常和哪些参数一起用
- -r 或 -R:递归复制目录,复制文件夹必须加,否则报「omitting directory」。
- -a:归档模式,等于 -dR --preserve=all,保留权限、所有者、时间戳、软链接。备份、部署最常见的就是 cp -av。
- -i:覆盖前询问,交互场景用。
- -n:不覆盖已存在的文件。
- -u:只复制更新的文件,增量备份用。
最常用的一条:
cp -av /var/www/app/ /backup/app_$(date +%F)/注意末尾的斜杠
这是个老坑。cp -a src dst,如果 dst 不存在,结果是 dst 变成 src 的副本;如果 dst 存在,结果是 dst/src。加不加斜杠、目标存不存在,结果不一样。写脚本前先在临时目录试一下,别在线上凭感觉敲。
-v 带来的副作用
复制几万个文件时,-v 会疯狂刷屏,SSH 连接都能被拖慢。这时候把输出重定向到日志:
cp -av src/ dst/ >> /var/log/backup.log 2>&1想看进度又不想要几十万行日志,可以用 rsync 替代,它的 --progress 和 --info 更友好,还支持增量同步和断点续传。cp 只适合小规模的一次性复制。
一个容易忽略的细节
cp 默认不保留时间戳,用 -a 才会保留。做打包和构建缓存时,时间戳不一致会导致增量编译判断出错,所以构建脚本里也应该养成加 -a 的习惯。