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

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

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

小:示例

假设在 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:\difference

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

答案1

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

如果你只是想看看哪些文件相同/不同,你可以使用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") 将仅显示“孤独”的文件而不移动它们。在测试了脚本并确信将移动正确的文件后,您可以将值更改为:变量"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"

答案2

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

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

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

它也正在积极开发中,因此你可以提交错误报告和功能请求。最棒的是,它是免费的。


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

WinMerge 的屏幕截图,显示了几种同步文件的方法

相关内容