Windows – compare two directory (each with multiple sub-directory and folder) and find files that are not present in either one of them in windows

cmd.exefile managementwindows

I want to compare two directory (including subfolders) for files (for example pictures) in two separate drives. I have thousands of files and are hidden inside subdirectory and folders.

Small: Example

Lets say in C: the following is list of folders and file

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: has similar folder structure (may not be exact, except folder 1 is same) but some files may be missing or additional

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

Now I need quick way (may be dos command line or software that can find files that are missing or additional and put the files in a new directory say D:\difference

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

Best Answer

A script to move the files is below...

If you just want to see which files are the same/different, you can use windiff. This might help with troubleshooting problems with the script.

So, for your example:

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

Windiff will open and show which files are:

  • Identical
  • Different (indicating which file is newer)
  • Left-only (file exists only in "first path" (C:\folder1)
  • Right-only (file exists only in "second path" (D:\folder1)

You can save the findings to a file using the command line option: -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]

Also, you can include X with -S to close windiff after writing the list like this:

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

You can combine the lists, so if you want a list of the files that exist in only (any) one of the paths:

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

You can only generate one "log" file at a time, so if you wanted to generate all 4 individual "log" files you would have to run windiff 4 times:

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

Note: Files that exist in both paths, but located in different folders, will be shown as "leftonly" or "rightonly".



If you want a script to move the files that exist in only one of the paths to a different folder, you can use the batch script below.

Notes:

  • I'm calling a file that exists in only one of the paths a "lonely" file.
  • The script below (with variable "domove=0") will only display "lonely" files without moving them. After you have tested the script and are confident that the correct files will be moved, you can change the value to: variable "domove=1" to have the "lonely" files displayed and moved.
  • In the script, set sdrive1, sdrive2, sfolder, and sdifffolder as necessary.
  • Alternately, set spath1, spath2, and spathdiff if that is more appropriate for your use.
  • If desired, the script could easily be modified to accept these paths from the command line.

I have made the following assumptions:

  • For each file in the "first path", the entire "second path" is searched for a matching "filename.ext".
  • If the file is NOT found in the "second path" (lonely file), it is moved to a "difference" folder.
  • No attempt is made to compare files that have matching filenames, but that functionality could easily be added.
  • No attempt is made to account for the possibility that multiple files could have the same name and be located in different subfolders of the "first path" (same for "second path"). If this happens for a file that is a "lonely" file, each of those files will be moved to the "difference" folder, overwriting any previously moved files of the same name.
  • After each file in the "first path" is searched for within the "second path", the process is repeated in the other direction, and for each file in the "second path", the entire "first path" is searched for a matching "filename.ext".

Here is the script:

@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

Here is the output testing the script with the sample fileset you described:

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"
Related Question