标题: [文件操作] [已解決]如何不让 robocopy 同步完全一致的文件? [打印本页]
作者: yu2n 时间: 2017-3-3 18:49 标题: [已解決]如何不让 robocopy 同步完全一致的文件?
本帖最后由 yu2n 于 2017-3-5 19:38 编辑
现有如下文件:- C:\USERS\YU2N\DESKTOP\TEST
- | robocopy 7z.bat
- |
- +---同步来源
- | A1.txt
- | A2.txt
- |
- \---同步目标
- A1.txt
- A2.txt
复制代码
其中所有 *.txt 中的内容完全一致,里面都是一个字符“A”。
使用“robocopy /mir 同步来源 同步目标”来同步这些完全一致的文件时,居然真的同步了,即使根本不需要同步~它们完全一样啊!!!
如果这些文件很大,且在网络上时,robocopy 的这个特性会让人崩溃。
以下是测试代码:(测试环境Win10 x64)- @echo off & cls
-
- :: 当前目录
- set "CurDir=%~dp0"
- set "CurDir=%CurDir:~0,-1%"
-
- :: 创建测试目录
- md "%CurDir%\同步来源" >nul 2>nul
- md "%CurDir%\同步目标" >nul 2>nul
-
- :: 创建测试文档
- echo A>"%CurDir%\同步来源\A1.txt"
- copy /y "%CurDir%\同步来源\A1.txt" "%CurDir%\同步来源\A2.txt"
- copy /y "%CurDir%\同步来源\*.txt" "%CurDir%\同步目标\*.txt"
-
- :: 修改“同步来源\A2.txt”的修改时间
- ping 127.1>nul
- echo A>"%CurDir%\同步来源\A2.txt"
-
- :: 如何让 robocopy 不同步“同步来源\A2.txt”?它与“同步目标\A2.txt”里面的内容完全一致。
- robocopy /mir "%CurDir%\同步来源" "%CurDir%\同步目标"
-
- :: xcopy /d /y "%CurDir%\同步来源" "%CurDir%\同步目标"
-
- 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。- '*************************************************************************************
- '使用 7-Zip 命令行压缩文件,若无文件更新,则压缩档的修改时间不会更新
- '*************************************************************************************
- Function CompressFolderBy7z(ByVal strSrcDir, ByVal strDesDir, Byval strPassword)
- Dim wso, fso, oExec, dtModifyDate, sApp7z, sMode, sInfo, sDesFile
- Dim objShell, objFolder, objItem
- Set wso = CreateObject("WScript.Shell")
- Set fso = CreateObject("Scripting.filesystemobject")
-
- '获取 7-Zip 命令行路径
- On Error Resume Next
- sApp7z = wso.ExpandenVironmentStrings(wso.RegRead("HKCU\SOFTWARE\7-Zip\Path"))
- On Error GoTo 0
- If fso.FileExists(sApp7z & "7za.exe") Then
- sApp7z = sApp7z & "7za.exe"
- ElseIf fso.FileExists(sApp7z & "7z.exe") Then
- sApp7z = sApp7z & "7z.exe"
- Else
- Msgbox "找不到 7za.exe 或 7z.exe,请安装 7-Zip 后使用本程序。", vbCritical, WScript.ScriptName
- WScript.Quit
- End If
-
- '设置备份文件夹位置(修正盘符与UNC标示)
- If fso.FolderExists(strSrcDir) = False Then Exit Function
- If Right(strDesDir, 1) = "\" Then strDesDir = Left(strDesDir, Len(strDesDir)-1)
- If InStr(strSrcDir, ":\") Then strDesDir = strDesDir & "\" & Split(strSrcDir, ":\")(0) & "\" & Split(strSrcDir, ":\")(1)
- If InStr(strSrcDir, "\\") Then strDesDir = strDesDir & "\" & Split(strSrcDir, "\\")(1)
- If Instr(strDesDir,"\") > 0 Then
- Dim arr : arr = Split(strDesDir,"\") : ReDim Preserve arr(UBound(arr)-1) : strDesDir = Join(arr,"\")
- End If
- If fso.FolderExists(strDesDir) = False Then wso.Run "cmd /u /c md """ & strDesDir & """", 0, True
-
- '设置目标文件(*.7z)位置
- sDesFile = strDesDir & "\" & (Split(strSrcDir,"\")(UBound(Split(strSrcDir,"\")))) & ".7z"
-
- '执行压缩操作,记录“修改时间”,取得执行结果
- If fso.FileExists(sDesFile) = False Then
- sMode = "a"
- Else
- sMode = "u"
- dtModifyDate = fso.GetFile(sDesFile).DateLastModified
- End If
- WScript.Echo Now() & " [" & UCase(sMode) & "] " & sDesFile
- If strPassword <> "" Then strPassword = "-p" & strPassword
- Set oExec = wso.Exec("""" & sApp7z & """ " & sMode & " " & strPassword & " -r- -ssw -t7z """ & _
- sDesFile & """ """ & strSrcDir & """")
- sInfo = oExec.StdOut.ReadAll
- 'Msgbox sInfo '调试-查看执行结果
-
- '无更新则还原修改时间
- If sMode = "u" And Instr(1, sInfo, "Items to compress: 0", vbTextCompare) > 0 Then
- Set objShell = CreateObject("Shell.Application")
- Set objFolder = objShell.NameSpace(fso.GetFile(sDesFile).ParentFolder.Path)
- For Each objItem In objFolder.Items
- If UCase(objItem.Path) = UCase(fso.GetFile(sDesFile).Path) Then
- sMode = "s" 'skip
- objItem.ModifyDate = dtModifyDate
- Exit For
- End If
- Next
- Set objShell = Nothing
- End If
-
- '返回结果
- If sMode = "s" Then
- WScript.Echo Now() & " ... [Skip]"
- Else
- WScript.Echo Now() & " ... [Ok]"
- End If
- CompressFolderBy7z = "[" & UCase(sMode) & "]" & sDesFile
- Set fso = Nothing
- Set wso = Nothing
-
- 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://bbs.bathome.net/) |
Powered by Discuz! 7.2 |