Linux Bash中复制目录仅覆盖旧文件:cp -au脚本执行异常求助
解决Bash脚本中目录复制耗时过长的问题
Hey Anna, 我来帮你搞定这个困扰~你遇到的问题是明明只修改了temp里的一个文件,但cp -au却会复制所有文件导致耗时很久,这大概率是因为cp在增量检查的效率上不如专门的同步工具,或者某些细节处理不够优化。
先分析问题根源
cp -au的-u参数理论上会只复制源文件比目标文件新或者目标文件不存在的内容,但实际执行时全量复制,可能有这两个原因:
cp在遍历目录时,会逐个检查文件的时间戳和属性,当目录文件数量多的时候,这个检查过程本身就会很慢;- 某些旧版本的
cp对$TEMP/.这种写法的处理不够智能,会强制遍历所有文件(包括隐藏文件),哪怕不需要复制。
最优解决方案:改用rsync工具
rsync是Linux下专门用于增量文件同步的工具,它的效率比cp高很多,默认就会通过时间戳+文件大小快速校验文件是否需要更新,完全符合你的需求。把脚本改成这样:
#!/bin/bash TEMP="/home/pi/project/temp/" TARGET="/home/pi/project/deployed/" rsync -av --update "$TEMP/" "$TARGET"
参数解释:
-a:归档模式,等价于-rlptgoD,会保留文件的权限、时间戳、递归遍历子目录等,和你原来的cp -a效果一致;-v:可选的 verbose 模式,能显示同步过程,方便你排查问题;--update:和cp -u的逻辑一样,仅复制源比目标新的文件,或者目标不存在的文件;- 注意
$TEMP/末尾的斜杠,代表复制目录内的所有内容(包括隐藏文件),和你原来的$TEMP/.效果相同,但rsync的处理更高效。
如果坚持用cp的优化小技巧
如果你不想换工具,可以试试这两个调整:
- 用
$TEMP/*代替$TEMP/.(但会跳过隐藏文件,如果不需要同步隐藏文件的话可以用); - 先手动对比修改过的文件的时间戳,确认它确实比目标目录里的对应文件新:
如果时间戳没问题,那大概率是ls -l "$TEMP/你的文件名" "$TARGET/你的文件名"cp的效率问题,还是推荐换成rsync。
内容的提问来源于stack exchange,提问作者Anna K




