如何让rsync在使用--no-relative时重命名目标目录中的重复文件?
解决rsync --no-relative下的同名文件重命名问题
rsync自带的-b --suffix确实只能处理目标目录已存在同名文件的情况,对于同一次传输中来自不同路径的同名文件,需要额外处理才能避免覆盖。以下是两种可行的方案:
方案一:预处理文件,添加路径前缀重命名
通过临时目录中转,给每个待传输文件添加来源路径的标识,再用rsync传输到目标目录,这样既保留了来源区分,又不会出现同名冲突。
以你的示例为例,执行以下脚本:
# 创建临时目录 temp_dir=$(mktemp -d) # 遍历所有待传输文件,复制到临时目录时重命名 for file in sourceDir2/file.txt sourceDir3/file.txt; do # 将路径中的斜杠替换为下划线,生成新文件名 new_name=$(echo "$file" | tr '/' '_') cp "$file" "$temp_dir/$new_name" done # 用rsync传输临时目录的文件到目标,同时保留-b选项处理目标已存在的文件 rsync --no-relative -b --suffix="_old" "$temp_dir"/* destDir # 删除临时目录 rm -rf "$temp_dir"
这样传输后,目标目录会得到sourceDir2_file.txt和sourceDir3_file.txt,既不会互相覆盖,也会在目标已有同名文件时自动添加_old后缀备份。
方案二:自动添加递增后缀处理同名文件
如果不需要保留路径标识,只需要确保文件名唯一,可以用脚本检测临时目录中的文件名,重复时自动添加递增数字后缀:
temp_dir=$(mktemp -d) for file in sourceDir2/file.txt sourceDir3/file.txt; do base_name=$(basename "$file") new_name="$base_name" counter=1 # 检查临时目录中是否已存在同名文件,存在则递增后缀 while [ -f "$temp_dir/$new_name" ]; do new_name="${base_name%.txt}_$counter.txt" counter=$((counter + 1)) done cp "$file" "$temp_dir/$new_name" done rsync --no-relative -b --suffix="_old" "$temp_dir"/* destDir rm -rf "$temp_dir"
执行后,目标目录会得到file.txt和file_1.txt(如果之前已经传输过sourceDir1的file.txt,那么这次的file.txt会被备份为file.txt_old,新的file.txt对应sourceDir2的文件,sourceDir3的文件则变为file_1.txt)。
补充说明
- 如果你需要频繁执行这类操作,可以把上述脚本封装成一个函数,方便调用。
mktemp -d会创建安全的临时目录,避免权限问题和命名冲突。
内容的提问来源于stack exchange,提问作者Ray
相关产品推荐
相关产品推荐

