如何递归比较两个文件夹并生成不同的文件和文件夹列表?

And*_*ong 8 file-management diff rsync file-comparison windows-7-backup

tl;dr 和一个例子

我正在寻找一种方法来递归比较两个文件夹并输出所有不同(按大小或按时间戳,à la rsync)的文件(和文件夹)的相对路径。

例如,说我有

C:\source\foo\a.txt
C:\source\foo\bar\b.txt
C:\source\foo\bar\c.txt
Run Code Online (Sandbox Code Playgroud)

C:\target\foo\a.txt
C:\target\foo\bar\b.txt
C:\target\foo\bar\d.txt
C:\target\foo\baz\
Run Code Online (Sandbox Code Playgroud)

并假设b.txt已在 下更改C:\source,因此更新。

然后给出一个神奇的脚本或命令,比如说magic C:\source C:\target,我希望输出是

foo\bar\b.txt
Run Code Online (Sandbox Code Playgroud)

或者,源文件夹或目标文件夹上的完整路径也是可以接受的:

C:\source\foo\bar\b.txt
Run Code Online (Sandbox Code Playgroud)

如示例所示,我不在乎已删除或创建的文件和文件夹!这应该使这项任务比其他任务简单得多。

我已经知道的...

我自己是 UNIX 开发人员,不会问这是否是我们正在处理的 UNIX 系统,但是唉。此外,这是针对自定义夜间备份解决方案,其中可靠性和数据完整性是重中之重,因此考虑到几周前我什至无法在批处理脚本中找出 for 循环,我很确定我缺乏正确执行此操作的经验,甚至确定执行此操作的最佳方法。

阅读http://www.howtoforge.com/backing-up-with-rsync-and-managing-previous-versions-history,我了解到 rsync 可以使用类似选项

--dry-run               # don't actually rsync (touch) any files
--itemize-changes       # list changes rsync _would_ have made
--out-format="%i|%n|"   # define an output format for the list of changes
Run Code Online (Sandbox Code Playgroud)

但是,我不喜欢依赖 Cygwin (cwRsync) 来使用 rsync,因为我已经很容易在我的 Cygwin 安装上运行快速而肮脏的实验,经常破坏环境并且需要每隔几周重新安装 Cygwin。这种反对夜间备份的“可靠”部分。

我还没有在 Windows 中找到任何像 rsync 这样的“规范”工具,至少没有任何支持上述选项的工具。此外,一般不会寻找软件,除非它是专门用于此目的的简单紧凑的工具——我更喜欢透明的、程序化的解决方案。对于备份文件这么重要的事情,依赖我看不懂或看不懂的软件或代码是可怕的!

回顾

我无法理解批处理脚本语法。接下来我将尝试 PowerShell。但是,鉴于此任务,怎么做? - 是否有一些我遗漏的明显路线?

And*_*ong 7

@Glytzhkof 在他的回答中推荐了 Robocopy,它非常适合我的需求。

tl;博士

C:\>robocopy.exe source target /l /e /zb /xx /xl /fp /ns /nc /ndl /np /njh /njs

                                C:\source\foo\bar\b.txt
Run Code Online (Sandbox Code Playgroud)

选项的详细信息和说明

Robocopy(维基百科)似乎广泛用于 Windows 系统管理;有据可查(TechNet);在Stack OverflowServer Fault上讨论的不仅仅是一个晦涩的问题,当然,在Super User 上也有讨论;提供一个特定的功能,而不是试图成为一个多用途的工具(这会导致膨胀和错误);此外,自 1997 年以来一直提供此特定功能。对我来说,所有这些因素都有助于“透明度”,尽管它是封闭源代码,让我放心。

Robocopy 是目前称为Windows Server 2003 Resource Kit Tools的一组工具的一部分。下载并安装后,我在我的问题中重新创建了场景并试了一下:

C:\>robocopy.exe source target /l /e /zb

-------------------------------------------------------------------------------
   ROBOCOPY     ::     Robust File Copy for Windows
-------------------------------------------------------------------------------

  Started : Thu May 01 09:08:20 2014

   Source : C:\source\
     Dest : C:\target\

    Files : *.*

  Options : *.* /L /S /E /COPY:DAT /ZB /R:1000000 /W:30

------------------------------------------------------------------------------

                           0    C:\source\
                           1    C:\source\foo\
        *EXTRA Dir        -1    C:\target\foo\baz\
                           2    C:\source\foo\bar\
          *EXTRA File                  1        d.txt
            Newer                      5        b.txt
            New File                   1        c.txt

------------------------------------------------------------------------------

               Total    Copied   Skipped  Mismatch    FAILED    Extras
    Dirs :         3         0         3         0         0         1
   Files :         3         2         1         0         0         1
   Bytes :         7         6         1         0         0         1
   Times :   0:00:00   0:00:00                       0:00:00   0:00:00

   Ended : Thu May 01 09:08:20 2014
Run Code Online (Sandbox Code Playgroud)

看起来挺好的!让我解释一下这些选项:

  • /l列出行动而不实际执行。
  • /e包括子目录,但与 不同的是/s,也包括空目录。
  • /zb在“重启”模式下复制,在拒绝访问时,“备份”模式;这似乎是最安全的方法;在这里阅读更多。

我不需要任何与复制相关的选项,因为我实际上没有执行任何操作。

无论如何,接下来,只需添加更多开关即可获得我想要的输出:

C:\>robocopy.exe source target /l /e /zb /xx /xl /fp /ns /nc /ndl /np /njh /njs

                                C:\source\foo\bar\b.txt
Run Code Online (Sandbox Code Playgroud)

再次,让我们来看看选项。

首先,我只关心修改过的文件和文件夹,所以:

  • /xx 排除“额外”的文件和目录——那些只存在于目标中的文件和目录。
  • /xl 排除“孤独”的文件和目录——那些只存在于源文件中的文件和目录。

其次,我想要相对路径(或至少是完整路径,而不仅仅是名称):

  • /fp 启用完整路径(不出所料,相对路径没有选项)。

第三,我想尽可能多地去除伐木绒毛,我惊喜地发现所有这些都是可去除的:

  • /ns 抑制文件大小。
  • /nc抑制类,例如 Newer
  • /ndl 禁止目录名称。
  • /np 抑制复制进度输出。
  • /njh 抑制作业标题。
  • /njs 抑制作业摘要。

你有它!


出于我的目的(创建更改文件的版本备份),我意识到我实际上也希望拥有每个修改文件的时间戳。只需添加/ts

C:\>robocopy.exe source target /l /e /zb /xx /xl /fp /ns /nc /ndl /np /njh /njs /ts

                         2014/05/01 15:20:42    C:\source\foo\bar\b.txt
Run Code Online (Sandbox Code Playgroud)