如何复制源目录文件到目标目录并解析目标目录软链接
问题描述
需要将源目录中的文件递归复制到目标目录,并解析目标目录中的所有软链接。
源目录结构:
source |-- dir1 | `-- file1 |-- dir2 | |-- dir4 | `-- file2 `-- dir3 `-- file3
目标目录初始结构:
dest |-- dir1 |-- dir2 -> dir1 `-- dir3
期望复制完成后的目标目录结构:
dest |-- dir1 | |-- dir4 | |-- file1 | `-- file2 |-- dir2 -> dir1 `-- dir3 `-- file3
当前尝试使用命令 cp -R source/. dest/(因其他原因无法使用shell通配符 *),但报错:cp: target dest/./dir2 is not a directory。
补充说明:
- 不能假设源目录中的所有目录都存在于目标目录中。
- 虽可通过创建source的tar包再解压到dest实现,但该方法繁琐冗余,希望用更简洁的方式。
解决方案
最优方案:使用rsync命令
直接用rsync替代cp即可,它能自动解析目标目录中的软链接,将内容写入链接指向的实际目录,完美解决问题:
rsync -a source/. dest/
命令说明
-a是归档模式,等价于-rlptgoD,包含递归复制、保留权限、时间戳、符号链接等特性,完全满足递归复制文件的需求。source/.指定复制source目录下的所有内容(不包含source目录本身),和你之前用cp的写法逻辑一致。rsync遇到目标是指向目录的软链接时,会自动跟随软链接写入实际目录,不会像cp那样因目标是软链接而非实体目录报错。
备选方案:cp结合find与readlink(若必须用cp)
如果受限于环境只能使用cp,可以用以下脚本逐个处理源目录条目,先解析目标路径的软链接再复制:
find source -mindepth 1 -print0 | while IFS= read -r -d '' item; do # 提取条目相对source的路径,拼接成目标路径 dest_path="dest/${item#source/}" # 解析目标路径所在目录的软链接,得到实际物理路径 real_dest_dir=$(readlink -f "$(dirname "$dest_path")") # 确保实际目录存在(兼容源目录有新目录的情况) mkdir -p "$real_dest_dir" # 复制条目到解析后的实际目录 cp -R "$item" "$real_dest_dir/" done
脚本说明
find source -mindepth 1 -print0:遍历source下所有内容(排除source本身),-print0用于处理含空格或特殊字符的路径。- 通过字符串截取得到每个条目在目标目录中的相对路径。
readlink -f解析目标目录路径中的软链接,获取真实的物理目录位置。mkdir -p确保目标物理目录存在,满足补充说明中“源目录可能有新目录”的要求。- 最后用
cp -R将源条目复制到真实目标目录中。
内容的提问来源于stack exchange,提问作者AVS Origami
相关产品推荐
相关产品推荐

