需要简单的文件比较而不需要区分

时间:2016-02-28 04:16:36

标签: c# windows diff

我在我的服务器上运行Windows 2008。

我已经使用Araxis进行差异化并喜欢它。但现在我有一个更独特的用例。我需要在我的服务器上的两个文件夹之间进行递归文件比较,其中两个文件夹中都存在数十万个文件。 99%的文件都是一样的,我已经知道了。一个文件夹树中存在一些文件,但另一个文件夹树不存在。我需要一种快速的方法来找到"差异文件"。我已经尝试过Araxis,而且由于文件量很大,它的速度太慢了。我怀疑Winmerge和其他人会同样很慢,因为他们试图对每个文件进行区分,这是我不需要的。

重要提示:文件无需进行文本或二进制比较。我不是在寻找差异。我正在寻找一个快速比较一个树中存在哪些文件而不是另一个文件夹的文件夹。差异工具太慢了,因为他们试图区分,而不是简单地查找哪个文件存在于一个地方而不是另一个地方。我正在寻找的工具只需要比较每个文件夹中的文件名,而不是更深入。

速度至关重要且内部内容差异化"是不必要的。

有这样的工具吗?

3 个答案:

答案 0 :(得分:0)

echo.|xcopy /L /s "directory1\*" "directory2"

应该为您提供与dir2 list

不同的dir1

答案 1 :(得分:0)

我也需要类似的东西,这个批处理文件就是我提出来的。我先在小树上试一下,看看它是如何表现的。

@ECHO OFF

SETLOCAL

REM Change these drive letters to ones that aren't already in use!
SET subst_letter_one=Y
SET subst_letter_two=Z

REM If exactly two arguments not specified then print help
IF [%1] NEQ [] IF [%2] NEQ [] IF [%3] EQU [] GOTO BEGIN
ECHO Usage: compare-folder [Folder 1] [Folder 2]
ECHO.
ECHO Very basic "exists in one but not in the other" type comparison of folder trees
ECHO Example: compare-folder "D:\somepath" "D:\anotherpath"
ECHO.
ECHO Before first-run, edit the two variables in the head of this batch file 
ECHO with spare drive letters that SUBST can use.
EXIT /B 0

:BEGIN
REM Use the SUBST command to map the two folders to temporary drive letters
SUBST %subst_letter_one%: %1
IF %ERRORLEVEL% NEQ 0 ( ECHO Problem mapping %1 to drive letter %subst_letter_one%. 
ECHO Did you try to map an already-used drive letter?
ECHO Exiting
EXIT /B 1 )
SUBST %subst_letter_two%: %2
IF %ERRORLEVEL% NEQ 0 ( ECHO Problem mapping %2 to drive letter %subst_letter_two%. 
ECHO Did you try to map an already-used drive letter? 
ECHO Exiting
EXIT /B 1 )

REM Main
ECHO.
ECHO ==================== FOLDER 1 ======================
ECHO.
ECHO Files and/or folders absent from %1 are listed below:
ECHO.

FOR /F "tokens=2* delims=:" %%i IN ('DIR %subst_letter_two%:\ /A /B /S /O:N') DO ( 
    IF NOT EXIST %subst_letter_one%:%%i ECHO %%i
)

ECHO.
ECHO ==================== FOLDER 2 ======================
ECHO.
ECHO Files and/or folders absent from %2 are listed below:
ECHO.

FOR /F "tokens=2* delims=:" %%i IN ('DIR %subst_letter_one%:\ /A /B /S /O:N') DO ( 
    IF NOT EXIST %subst_letter_two%:%%i ECHO %%i
)

REM Unmap temporary drive letters
SUBST %subst_letter_one%: /D
IF %ERRORLEVEL% NEQ 0 ( ECHO Problem unmapping letter %subst_letter_one%.
ECHO Exiting
EXIT /B 1 )
SUBST %subst_letter_two%: /D
IF %ERRORLEVEL% NEQ 0 ( ECHO Problem unmapping letter %subst_letter_two%.
ECHO Exiting
EXIT /B 1 )

ENDLOCAL

答案 2 :(得分:0)

我最终在c#中编写了一个自定义工具。完整的源代码如下。它工作得很好,我现在在我的生产服务器上多次使用它。它的唯一目的是比较两个文件夹树并将任何文件/文件夹添加到目标,这只存在于源中。 它不会尝试比较两个地方都存在的文件。 如果两个树中存在同名文件,并且在相同的相对位置,则会忽略该文件。

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using System.Configuration;
using System.IO;

namespace SyncFolders {
 class Program {
  private static string rootSourcePath = ConfigurationManager.AppSettings["RootSourcePath"];
  private static string rootDestinationPath = ConfigurationManager.AppSettings["RootDestinationPath"];
  private static int _itemsSynced = 0;

  static void Main(string[] args) {
   if (Directory.Exists(rootSourcePath)) {
    if (Directory.Exists(rootDestinationPath)) {
     var startTime = DateTime.Now;
     Console.WriteLine("Source: " + rootSourcePath);
     Console.WriteLine("Destination: " + rootDestinationPath);
     Console.WriteLine("You are about to copy any DIFFERENT folders/files from source to destination. Continue?");
     Console.ReadLine();

     DirectoryInfo source = new DirectoryInfo(rootSourcePath);

     WalkDirectoryTree(source, rootDestinationPath);

     Console.WriteLine("");
     Console.WriteLine("Started at " + startTime);
     Console.WriteLine("Finished at " + DateTime.Now);

     Console.WriteLine("");

     if (_itemsSynced > 0)
      Console.WriteLine("Folders/files added: " + _itemsSynced);
     else
      Console.WriteLine("Everything was already in sync!");

     Console.ReadLine();
    } else {
     Console.WriteLine("Folder not found: " + rootDestinationPath);
     Console.ReadLine();
    }
   } else {
    Console.WriteLine("Folder not found: " + rootSourcePath);
    Console.ReadLine();
   }
  }

  private static void WalkDirectoryTree(DirectoryInfo source, string destination) {
   System.IO.FileInfo[] files = null;
   System.IO.DirectoryInfo[] subDirs = null;

   files = source.GetFiles("*.*");

   if (files != null) {
    foreach(System.IO.FileInfo fi in files) {
     string fullSourcePath = fi.FullName;
     string fullDestinationPath = fi.FullName.Replace(source.FullName, destination);

     if (!File.Exists(fullDestinationPath)) {
      File.Copy(fullSourcePath, fullDestinationPath);
      Console.WriteLine(fullSourcePath);
      _itemsSynced++;
     }
    }

    // Now find all the subdirectories under this directory.
    subDirs = source.GetDirectories();

    foreach(System.IO.DirectoryInfo dirInfo in subDirs) {
     string fullSourcePath = dirInfo.FullName;
     string fullDestinationPath = fullSourcePath.Replace(source.FullName, destination);

     if (!Directory.Exists(fullDestinationPath)) {
      Directory.CreateDirectory(fullDestinationPath);
      Console.WriteLine(fullSourcePath);
      _itemsSynced++;
     }

     // Resursive call for each subdirectory.
     WalkDirectoryTree(dirInfo, fullDestinationPath);
    }
   }
  }
 }
}