Linux cp 报错 cannot overwrite non-directory with directory:原因和解决方法

cp -r pojie/ wpa-dictionary/pojie
# cp: cannot overwrite non-directory 'wpa-dictionary/pojie' with directory 'pojie/'

这个错误不是 cp 参数写错,而是目标路径 wpa-dictionary/pojie 已经存在一个普通文件,不是目录。

诊断

ls -ld wpa-dictionary/pojie

如果输出以 - 开头,说明是普通文件:

-rw-r--r-- 1 root root 1234 Jun 15 wpa-dictionary/pojie

如果是目录会以 d 开头:

drwxr-xr-x 2 root root 4096 Jun 15 wpa-dictionary/pojie

解决方案

方案 1:删除目标文件后再复制

rm -f wpa-dictionary/pojie
cp -r pojie wpa-dictionary/

方案 2:复制到不同名称

cp -r pojie wpa-dictionary/pojie_backup

方案 3:先移动目标文件

mv wpa-dictionary/pojie wpa-dictionary/pojie.bak
cp -r pojie wpa-dictionary/

cp 目录行为说明

cp -r src dst 的行为取决于 dst 是否存在:

目标是否存在行为
dst 不存在src 复制为 dst(改名)
dst 是目录src 整体放进 dst/src
dst 是普通文件报错:cannot overwrite non-directory

例如:

# 目标目录 backup/ 不存在
cp -r project/ backup/
# 结果:backup/ 就是 project/ 的副本

# 目标目录 backup/ 已存在
cp -r project/ backup/
# 结果:backup/project/(嵌套了一层)

注意末尾斜杠的影响:cp -r pojie/ dstcp -r pojie dst 行为可能不同(前者复制内容,后者复制整个目录)。

rsync 作为替代

目录同步推荐用 rsync,语义更清晰,且支持增量更新:

# 把 pojie/ 的内容同步到 wpa-dictionary/pojie/
rsync -av pojie/ wpa-dictionary/pojie/

# 只复制新文件,跳过已存在的
rsync -av --ignore-existing pojie/ wpa-dictionary/pojie/

# 删除目标中源没有的文件(镜像同步)
rsync -av --delete pojie/ wpa-dictionary/pojie/

rsync 在处理已存在目标时不会报上面的错误,会直接合并或覆盖。