Rsync配置需求:校验和相同时保留目标文件原时间戳
如何让rsync仅在文件内容不同时更新目标文件及其时间戳
我明白你的需求:想用rsync同步目录,但希望内容完全一致的文件保留目标端的原时间戳,只有当内容真的变化时,才更新文件并同步源文件的时间戳。咱们一步步拆解问题和解决方案:
问题场景
初始状态下,两个文件内容一致但时间戳不同:
~/Homepage $ ls -l harp_output/BingSiteAuth.xml harp_netlify/BingSiteAuth.xml -rw-r--r-- 1 david david 81 14. Mai 07:58 harp_netlify/BingSiteAuth.xml -rw-r--r-- 1 david david 81 14. Mai 08:10 harp_output/BingSiteAuth.xml
用cmp验证内容完全一致:
~/Homepage $ cmp harp_output/BingSiteAuth.xml harp_netlify/BingSiteAuth.xml; echo $? 0
你执行了这条rsync命令:
~/Homepage $ rsync -cav --delete harp_output/ harp_netlify/
结果却发现,内容一致的文件时间戳还是被同步成了源文件的:
~/Homepage $ ls -l harp_output/BingSiteAuth.xml harp_netlify/BingSiteAuth.xml -rw-r--r-- 1 david david 81 14. Mai 08:10 harp_netlify/BingSiteAuth.xml -rw-r--r-- 1 david david 81 14. Mai 08:10 harp_output/BingSiteAuth.xml
而你期望的是:
~/Homepage $ ls -l harp_output/BingSiteAuth.xml harp_netlify/BingSiteAuth.xml -rw-r--r-- 1 david david 81 14. Mai 07:58 harp_netlify/BingSiteAuth.xml -rw-r--r-- 1 david david 81 14. Mai 08:10 harp_output/BingSiteAuth.xml
问题根源
问题出在rsync的-a(归档模式)参数上——它包含了-t(--times)选项,这个选项的作用是强制把目标文件的修改时间同步成源文件的,不管内容是否相同。哪怕你加了-c(--checksum)让rsync用校验和判断内容一致性,-t依然会“固执地”同步时间戳,哪怕内容完全没变化。
解决方案
遗憾的是,rsync没有直接的单参数组合能完美满足你的需求,但我们有两种可行的方式:
方案1:用Shell脚本实现精确需求
这个脚本会严格按照你的要求执行:内容一致则保留目标时间戳,内容不同则同步文件和时间戳,同时处理删除操作:
#!/bin/bash # 定义源目录和目标目录 SOURCE_DIR="harp_output/" DEST_DIR="harp_netlify/" # 递归遍历源目录的所有文件 find "$SOURCE_DIR" -type f | while read -r src_file; do # 转换为目标文件路径 dest_file="${src_file/$SOURCE_DIR/$DEST_DIR}" # 如果目标文件不存在,直接同步(包含时间戳) if [ ! -f "$dest_file" ]; then rsync -av "$src_file" "$dest_file" continue fi # 计算源文件和目标文件的SHA256校验和(也可以换成md5sum) src_sum=$(sha256sum "$src_file" | awk '{print $1}') dest_sum=$(sha256sum "$dest_file" | awk '{print $1}') # 校验和不同时,同步文件和时间戳 if [ "$src_sum" != "$dest_sum" ]; then rsync -av "$src_file" "$dest_file" fi done # 删除目标目录中源目录不存在的文件 rsync -av --delete --dry-run "$SOURCE_DIR" "$DEST_DIR" | grep 'deleting' | awk '{print $2}' | while read -r del_file; do rm -f "${DEST_DIR}${del_file}" done
把这个脚本保存为sync_with_checksum.sh,赋予执行权限(chmod +x sync_with_checksum.sh)后运行即可。
方案2:折衷的rsync参数组合
如果你不想写脚本,可以用两条rsync命令接近你的需求:
第一条命令同步文件,但不强制同步时间戳(用-rlpgoD代替-a,去掉-t):
rsync -crlpgoDv --delete harp_output/ harp_netlify/
这条命令会:
- 内容一致的文件不会被传输,目标时间戳保持不变
- 内容不同的文件会被传输,但目标时间戳是rsync执行的时间,不是源文件的时间戳
如果需要同步更新文件的时间戳,再执行第二条命令:
rsync -crtv --delete --existing harp_output/ harp_netlify/
这条命令会仅同步那些已存在且内容不同的文件的时间戳(--existing会忽略目标目录中没有的文件)。
内容的提问来源于stack exchange,提问作者duxsco
相关产品推荐
相关产品推荐

