Board logo

标题: [文件操作] [已解決]如何不让 robocopy 同步完全一致的文件? [打印本页]

作者: yu2n    时间: 2017-3-3 18:49     标题: [已解決]如何不让 robocopy 同步完全一致的文件?

本帖最后由 yu2n 于 2017-3-5 19:38 编辑

现有如下文件:
  1. C:\USERS\YU2N\DESKTOP\TEST
  2. |   robocopy 7z.bat
  3. |
  4. +---同步来源
  5. |       A1.txt
  6. |       A2.txt
  7. |
  8. \---同步目标
  9.         A1.txt
  10.         A2.txt
复制代码
其中所有 *.txt 中的内容完全一致,里面都是一个字符“A”。
使用“robocopy /mir 同步来源 同步目标”来同步这些完全一致的文件时,居然真的同步了,即使根本不需要同步~它们完全一样啊!!!
如果这些文件很大,且在网络上时,robocopy 的这个特性会让人崩溃。

以下是测试代码:(测试环境Win10 x64)
  1. @echo off & cls
  2. :: 当前目录
  3. set "CurDir=%~dp0"            
  4. set "CurDir=%CurDir:~0,-1%"
  5. :: 创建测试目录
  6. md "%CurDir%\同步来源" >nul 2>nul
  7. md "%CurDir%\同步目标" >nul 2>nul
  8. :: 创建测试文档
  9. echo A>"%CurDir%\同步来源\A1.txt"
  10. copy /y "%CurDir%\同步来源\A1.txt" "%CurDir%\同步来源\A2.txt"
  11. copy /y "%CurDir%\同步来源\*.txt" "%CurDir%\同步目标\*.txt"
  12. :: 修改“同步来源\A2.txt”的修改时间
  13. ping 127.1>nul
  14. echo A>"%CurDir%\同步来源\A2.txt"
  15. :: 如何让 robocopy 不同步“同步来源\A2.txt”?它与“同步目标\A2.txt”里面的内容完全一致。
  16. robocopy /mir "%CurDir%\同步来源" "%CurDir%\同步目标"
  17. :: xcopy /d /y  "%CurDir%\同步来源" "%CurDir%\同步目标"
  18. pause
复制代码
测试结果:“同步来源\A2.txt” 每次都会被 robocopy 同步,很无奈。

问题来了,请问牛人们,如何不让 robocopy 同步完全一致的文件?
作者: 523066680    时间: 2017-3-3 21:26

我记得不会复制完全一致的文件啊,莫非是文件的"修改日期"被更新了?
作者: yu2n    时间: 2017-3-4 00:14

回复 2# 523066680


    我试过将文件内容修改成一致后,再把修改时间也改为一致,仍然会同步。
作者: Nsqs    时间: 2017-3-4 00:28

mir是镜像复制,当然会一样了
作者: yu2n    时间: 2017-3-4 10:22

本帖最后由 yu2n 于 2017-3-4 10:27 编辑

回复 4# Nsqs

如果文件内容(校验)完全一致,只是文件属性(修改时间等)不同,那么只更新文件属性不好么?
为什么要重新复制文件内容+文件属性呢?

有时候,宁愿多读(校验)一次文件,也不愿意去复写一次文件。
作者: ygqiang    时间: 2017-3-4 10:49

回复 5# yu2n


    robocopy /mir

这个得问微软为啥开发这种功能的。
作者: 523066680    时间: 2017-3-4 11:21

本帖最后由 523066680 于 2017-3-4 11:50 编辑

em .. 经常用 Robocopy 同步整盘文件到移动硬盘,印象里没有对已经存在的同文件再次复制的情况 ……
不然的话一定超慢

--------------------------- 2017-03-04 ---------------------------
重新看了你的批处理,把这部分去掉后 Robocopy 就不会重新复制了啊

:: 修改“同步来源\A2.txt”的修改时间
ping 127.1>nul
echo A>"%CurDir%\同步来源\A2.txt"
-----------------------------------------------------------------------

才发现楼主好像是要抛开时间对比,根据文件内容判断。而 Robocopy (大概)就是以修改时间作为依据的

如果要抛开"修改时间"的区别,根据文件内容作为是否复制的判断,
应该搞一套 MD5 之类的校验方案,或者抽样校验,但比日期判断要耗时了。

如果说到大文件,比如媒体文件、镜像文件,通常情况下也没有人去手动 touch 它的"日期" 啊,感觉并无大碍。
作者: yu2n    时间: 2017-3-4 13:19

本帖最后由 yu2n 于 2017-3-4 13:47 编辑

回复 7# 523066680

    恩,我也很认同。

我这里的实际情况是这样的:
1. 用 7z.exe 去添加、更新压缩文件到本机指定目录。
2. 用 robocopy 将本机指定目录同步到网络磁盘(UNC)。
我发现更新压缩文件(步骤1)时,就算里面的内容没变,它的修改时间也会更改。然后robocopy就会再去复制一次(步骤2),真的超慢。

求推荐按文件内容同步的软件(适用于Windows 网络磁盘)。


——————————————————————————
或许,这是 7z.exe 的锅?不该怪 robocopy。
如果是这样,我应该问:
7z.exe 更新压缩档操作时,为什么任何文件都没有更新的情况下,它还要去修改了压缩档的“修改时间”?

如果 7z.exe 愿意背锅的话,事情还比较简单。对 7z.exe 返回值进行判断,如果它确实什么事情都没做,就把“修改时间”改回去。
作者: yu2n    时间: 2017-3-4 13:20

本帖最后由 yu2n 于 2017-3-4 13:49 编辑

回复 6# ygqiang


    我只能說~希望可以做的更好。
作者: 523066680    时间: 2017-3-4 14:24

本帖最后由 523066680 于 2017-3-4 15:21 编辑

我觉得这种情况可能需要自己着手写程序/脚本。
一点思路:
1、为网络端的压缩包建立校验值列表,同步的时候先计算本地压缩包的校验值,判断校验值是否一致。
这个操作仅针对压缩包类的文件。

2、如果可以对网络端的压缩包执行 7z -l,输出中包含文件名、修改日期的信息,对比本地压缩包的 7z -l 输出,如果完全一致,
则无需同步。
作者: ygqiang    时间: 2017-3-4 15:48

回复 8# yu2n


    也许换别的类似7z压缩软件,就能解决问题了?
作者: yu2n    时间: 2017-3-5 19:42

回复 10# 523066680


    已搞定。

我的方法是,先获取压缩文件的修改时间T1,然后运行7z.exe,如果没有更新文件操作,就把压缩文件的修改时间改回到T1。
  1. '*************************************************************************************
  2. '使用 7-Zip 命令行压缩文件,若无文件更新,则压缩档的修改时间不会更新
  3. '*************************************************************************************
  4. Function CompressFolderBy7z(ByVal strSrcDir, ByVal strDesDir, Byval strPassword)
  5. Dim wso, fso, oExec, dtModifyDate, sApp7z, sMode, sInfo, sDesFile
  6. Dim objShell, objFolder, objItem
  7. Set wso = CreateObject("WScript.Shell")
  8. Set fso = CreateObject("Scripting.filesystemobject")
  9. '获取 7-Zip 命令行路径
  10. On Error Resume Next
  11. sApp7z = wso.ExpandenVironmentStrings(wso.RegRead("HKCU\SOFTWARE\7-Zip\Path"))
  12. On Error GoTo 0
  13. If fso.FileExists(sApp7z & "7za.exe") Then
  14. sApp7z = sApp7z & "7za.exe"
  15. ElseIf fso.FileExists(sApp7z & "7z.exe") Then
  16. sApp7z = sApp7z & "7z.exe"
  17. Else
  18. Msgbox "找不到 7za.exe 或 7z.exe,请安装 7-Zip 后使用本程序。", vbCritical, WScript.ScriptName
  19. WScript.Quit
  20. End If
  21. '设置备份文件夹位置(修正盘符与UNC标示)
  22. If fso.FolderExists(strSrcDir) = False Then Exit Function
  23. If Right(strDesDir, 1) = "\" Then strDesDir = Left(strDesDir, Len(strDesDir)-1)
  24. If InStr(strSrcDir, ":\") Then strDesDir = strDesDir & "\" & Split(strSrcDir, ":\")(0) & "\" & Split(strSrcDir, ":\")(1)
  25. If InStr(strSrcDir, "\\") Then strDesDir = strDesDir & "\" & Split(strSrcDir, "\\")(1)
  26. If Instr(strDesDir,"\") > 0 Then
  27. Dim arr : arr = Split(strDesDir,"\") : ReDim Preserve arr(UBound(arr)-1) : strDesDir = Join(arr,"\")
  28. End If
  29. If fso.FolderExists(strDesDir) = False Then wso.Run "cmd /u /c md """ & strDesDir & """", 0, True
  30. '设置目标文件(*.7z)位置
  31. sDesFile = strDesDir & "\" & (Split(strSrcDir,"\")(UBound(Split(strSrcDir,"\")))) & ".7z"
  32. '执行压缩操作,记录“修改时间”,取得执行结果
  33. If fso.FileExists(sDesFile) = False Then
  34. sMode = "a"
  35. Else
  36. sMode = "u"
  37. dtModifyDate = fso.GetFile(sDesFile).DateLastModified
  38. End If
  39. WScript.Echo Now() & " [" & UCase(sMode) & "] " & sDesFile
  40. If strPassword <> "" Then strPassword = "-p" & strPassword
  41. Set oExec = wso.Exec("""" & sApp7z & """ " & sMode & " " & strPassword & " -r- -ssw -t7z """ & _
  42. sDesFile & """ """ & strSrcDir & """")
  43. sInfo = oExec.StdOut.ReadAll
  44. 'Msgbox sInfo '调试-查看执行结果
  45. '无更新则还原修改时间
  46. If sMode = "u" And Instr(1, sInfo, "Items to compress: 0", vbTextCompare) > 0 Then
  47. Set objShell = CreateObject("Shell.Application")
  48. Set objFolder = objShell.NameSpace(fso.GetFile(sDesFile).ParentFolder.Path)
  49. For Each objItem In objFolder.Items
  50. If UCase(objItem.Path) = UCase(fso.GetFile(sDesFile).Path) Then
  51. sMode = "s" 'skip
  52. objItem.ModifyDate = dtModifyDate
  53. Exit For
  54. End If
  55. Next
  56. Set objShell = Nothing
  57. End If
  58. '返回结果
  59. If sMode = "s" Then
  60. WScript.Echo Now() & " ... [Skip]"
  61. Else
  62. WScript.Echo Now() & " ... [Ok]"
  63. End If
  64. CompressFolderBy7z = "[" & UCase(sMode) & "]" & sDesFile
  65. Set fso = Nothing
  66. Set wso = Nothing
  67. End Function
复制代码

作者: nwm310    时间: 2017-11-1 15:38

本帖最后由 nwm310 于 2017-11-1 16:34 编辑

回复 8# yu2n


   
7z.exe 更新压缩档操作时,为什么任何文件都没有更新的情况下,它还要去修改了压缩档的“修改时间”?

用 7zFM.exe打開 a.7z
然後   7z.exe  u  a.7z  data\

會出現錯誤訊息
System ERROR:
程序無法存取檔案,因為檔案正由另一個程序使用。

a.7z旁邊出現 a.7z.tmp

==================================
用 -stl

If -stl switch is specified, 7-Zip sets timestamp for archive file as timestamp from the most recently modified file in that archive.

但,這有風險
7z.exe u -stl a.7z data\
7z.exe u -stl a.7z data\  old-time.txt
第二行的a.7z的修改時間會和第一行的一樣
除非把old-time.txt放進 data\ 資料夾
使data\資料夾的修改時間跟著改變




欢迎光临 批处理之家 (http://www.bathome.net/) Powered by Discuz! 7.2