比较两个目录(每个目录有多个子目录和文件夹),并查找Windows中任何一个目录中都不存在的文件


2

我想比较两个独立驱动器中的文件(例如图片)的两个目录(包括子文件夹)。我有数千个文件,隐藏在子目录和文件夹中。

小:例子

让我们在C中说:以下是文件夹和文件列表

C:\folder1
          file01.jpeg
          file02.jpeg

C:\folder1\folder2 
          file10.jpeg

C:\folder1\folder2\folder3 
          file04.jpeg
          file05.jpeg

C:\folder1\folder4

          file06.jpeg
          file07.jpeg
          file03.jpeg

D:具有相似的文件夹结构(可能不准确,除了文件夹1相同)但有些文件可能丢失或有其他文件

D:\folder1
          file01.jpeg
          file08.jpeg

D:\folder1\folder2 
          file03.jpeg

D:\folder1\folder2\folder3 
          file04.jpeg

D:\folder1\folder4
          file06.jpeg
          file07.jpeg
          file09.jpeg

现在我需要快速的方法(可能是dos命令行或软件,可以找到丢失或额外的文件,并将文件放在一个新的目录中说D:\差异

D:\difference
    file02.jpeg 
    file05.jpeg
    file08.jpeg 
    file09.jpeg
    file10.jpeg     


您的示例中似乎存在一些不一致之处。告诉你的唯一的区别和。但是,并且只存在于树中。另外两个问题尚不清楚:1)您是否希望脚本忽略位于两个文件夹的不同子路径中的事实?2)您是否要比较每个路径中的文件并执行某些操作,如果两个路径中都存在文件但文件不同?file08.jpeg file09.jpegfile10.jpegfile02.jpegfile05.jpegC:file03.jpeg
Kevin Fegan 2014年

您是否需要将列表输出到控制台或文件,或者像WinMerge这样的GUI程序是否足够?
Synetech 2014年

@KevinFegan我修复了不一致性。看到更新。(1)是的我可以忽略文件的位置(2)我想只是比较文件而不管它们位于何处,可能是池,比较可能是实现策略。
rdorlearn 2014年

@Synetech最终 - 我想复制文件并放入新文件夹 - 而不仅仅是列表。
rdorlearn 2014年

Answers:


5

移动文件的脚本如下......

如果您只想查看哪些文件相同/不同,则可以使用windiff。这可能有助于解决脚本问题。

所以,举个例子:

C:> windiff c:\folder1 d:\folder1

Windiff将打开并显示哪些文件是:

  • 相同
  • 不同(表示哪个文件较新)
  • 仅左(文件仅存在于“第一个路径”(C:\ folder1)中
  • 仅右(文件仅存在于“第二路径”(D:\ folder1)中)

您可以使用命令行选项将结果保存到文件中-S

-SS N:\path\filename.ext   [save list of identical files to filename.ext]
-SD N:\path\filename.ext   [save list of different files to filename.ext]
-SL N:\path\filename.ext   [save list of left-only files to filename.ext]
-SR N:\path\filename.ext   [save list of right-only files to filename.ext]

另外,还可以包括X-S关闭windiff编写清单这样后:

-SRX N:\path\filename.ext   [save list of right-only files to filename.ext]

您可以组合列表,因此如果您想要仅存在于(任何)一个路径中的文件列表:

C:> windiff -SLRX leftrightonly.txt c:\folder1 d:\folder1

您一次只能生成一个“日志”文件,因此如果您想生成所有4个单独的“日志”文件,则必须运行windiff 4次:

C:> windiff -SSX same.txt c:\folder1 d:\folder1
C:> windiff -SDX different.txt c:\folder1 d:\folder1
C:> windiff -SLX leftonly.txt c:\folder1 d:\folder1
C:> windiff -SRX rightonly.txt c:\folder1 d:\folder1

注意:存在于两个路径中但位于不同文件夹中的文件将显示为“leftonly”或“rightonly”。



如果希望脚本将仅存在于其中一个路径中的文件移动到其他文件夹,则可以使用下面的批处理脚本。

笔记:

  • 我正在调用一个文件,该文件只存在于一个“孤独”文件的路径中。
  • 下面的脚本(带变量"domove=0")只显示“孤独”文件而不移动它们。在测试脚本并确信将移动正确的文件后,您可以将值更改为:variable "domove=1"以显示和移动“孤独”文件。
  • 在脚本中,设置sdrive1sdrive2sfolder,和sdifffolder必要的。
  • 或者,设置spath1spath2以及spathdiff是否更适合您的使用。
  • 如果需要,可以轻松修改脚本以从命令行接受这些路径。

我做了以下假设:

  • 对于“第一路径”中的每个文件,搜索整个“第二路径”以寻找匹配的“filename.ext”。
  • 如果在“第二个路径”(孤立文件)中找不到该文件,则将其移动到“差异”文件夹。
  • 不会尝试比较具有匹配文件名的文件,但可以轻松添加该功能。
  • 没有尝试考虑多个文件可以具有相同名称并且位于“第一路径”的不同子文件夹中的可能性(“第二路径”相同)。如果对于“孤独”文件的文件发生这种情况,则每个文件都将移动到“差异”文件夹,覆盖以前移动的任何同名文件。
  • 在“第一路径”中的每个文件在“第二路径”内搜索之后,在另一个方向上重复该过程,并且对于“第二路径”中的每个文件,搜索整个“第一路径”以寻找匹配“FILENAME.EXT”。

这是脚本:

@echo off

rem use "domove" for testing
rem if "%domove%" !=1, "lonely" files found will only be displayed (not moved).
rem if "%domove%"  =1, "lonely" files found will be displayed and moved.
set "domove=0"

set "sdrive1=C:\"
set "sdrive2=D:\"
set "sfolder=folder1"
set "sdifffolder=difference"

set "spath1=%sdrive1%%sfolder%"
set "spath2=%sdrive2%%sfolder%"
set "spathdiff=%sdrive2%%sdifffolder%"
rem spath1=C:\folder1, spath2=D:\folder1, spathdiff=D:\difference

rem ***************************************************

rem check if "path1" and "path2" exist
if exist "%spath1%" if exist "%spath2%" goto :check2
if not exist "%spath1%" echo Error: Path1:"%spath1%" does not exist.>&2
if not exist "%spath2%" echo Error: Path2:"%spath2%" does not exist.>&2
goto :EOF



:check2

    rem check if "path1" is empty (no files)
    dir /a-d /s /b "%spath1%">nul 2>&1
    if %errorlevel% EQU 0 goto :check3
    echo Error: Path1:"%spath1%" is empty (no files).>&2
    goto :EOF



:check3

    rem check if "path2" is empty (no files)
    dir /a-d /s /b "%spath2%">nul 2>&1
    if %errorlevel% EQU 0 goto :check4
    echo Error: Path2:"%spath2%" is empty (no files).>&2
    goto :EOF



:check4

    rem check if "%spathdiff%" exists, but is a file (error)
    if not exist "%spathdiff%" goto :start
    if exist "%spathdiff%\*" goto :start
    echo Error: Folder "%spathdiff%" conflicts with a file with the same name.>&2
    goto :EOF



:start

    rem get a list of all files in "first path", call :work1
    rem passing "(path1:)C:\path\...\filename.ext", "filename.ext", and "D:\path2"
    for /f "usebackq delims=" %%f in (`dir /s /b /a-d "%spath1%"`) do call :work1 "%%~f" "%%~nxf" "%spath2%"

    rem reverse the paths:
    rem get a list of all files in "second path", call :work1
    rem passing "(path2:)D:\path\...\filename.ext", "filename.ext", and "C:\path1"
    for /f "usebackq delims=" %%f in (`dir /s /b /a-d "%spath2%"`) do call :work1 "%%~f" "%%~nxf" "%spath1%"

    rem done, exit
    goto :EOF



:work1

    set "w1full=%~1"
    set "w1file=%~2"
    set "wpath2=%~3"

    rem "%w1file%" is the "target" "filename.ext" from "first path" to look for (in "second path").
    for /f "usebackq delims=" %%g in (`dir /s /b /a-d "%wpath2%"`) do call :work2 "%%~nxg" "%w1file%" "w1file"

    rem if "target" "filename.ext" from "first path" was found in the "second path",
    rem it is now empty. it means:
    rem file is somewhere in both paths... no action. go get next file from "first path"
    if "%w1file%."=="." goto :EOF

    rem at this point, "%w1file%" ("%w1full%") is a "lonely" file
    rem "%w1file%" only exists in "path1" move it to "difference" path
    rem additional checks might be necessary here
    rem to see if this file already exists in "difference" path
    if not exist "%spathdiff%" md "%spathdiff%">nul 2>&1
    echo Found "lonely" file %w1file%:   move "%w1full%" "%spathdiff%"
    if %domove% EQU 1 move /y "%w1full%" "%spathdiff%">nul 2>&1
    rem you can test %errorlevel% here for error: %errorlevel%=0 if no error

    rem go get next file from "first path"
    goto :EOF



:work2

    rem %1 is "current" "filename.ext" from "second path"
    rem %2 is "target" "filename.ext" from "first path"

    rem if "target" "filename.ext" is empty, return for more
    if "%~2."=="." goto :EOF

    rem if file from "first path" is found in "second path", 
    rem "clear" the variable holding the filename of the "target" "filename.ext" from "first path"
    rem additional checks might be necessary here
    rem to "compare" the two files
    if /I "%~1"=="%~2" set "%~3="
    goto :EOF

以下是使用您描述的示例文件集测试脚本的输出:

Found "lonely" file file02.jpeg:   move "c:\folder1\file02.jpeg" "d:\difference"
Found "lonely" file file10.jpeg:   move "c:\folder1\folder2\file10.jpeg" "d:\difference"
Found "lonely" file file05.jpeg:   move "c:\folder1\folder2\folder3\file05.jpeg" "d:\difference"
Found "lonely" file file08.jpeg:   move "d:\folder1\file08.jpeg" "d:\difference"
Found "lonely" file file09.jpeg:   move "d:\folder1\folder4\file09.jpeg" "d:\difference"

在你的问题中,你说你想把文件“放”到一个新目录中,所以我把它当作move文件来表示。如果您想要copy文件,请更改movecopy显示和移动文件的行。
凯文费根2014年

3

如果您的目标只是检测一个文件夹中存在哪些文件并复制它们,那么您可以使用文件同步程序。有很多可以完成这项工作的人。

文件夹比较程序绝对有利于更好地控制,因为您可以查看差异,它们通常也有更精细的比较参数。您表示您只是想复制文件而不是获取列表或将其集成到脚本中,因此GUI程序可能适合您的情况。

为此目的最好的之一是WinMerge。它不仅可以让您比较两个目录的内容,还可以提供隐藏相同文件的各种过滤器,但它可以非常轻松地复制您想要的文件(图1)。

它也是积极开发的,因此您可以提交错误报告和功能请求。最重要的是,它是免费的。


图1:WinMerge有几种同步文件的方法

WinMerge的屏幕截图,其中包含几种同步文件的方法

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.