Compare two folders and output missing files in both folders

I would like to compare two folders, strictly for filenames. (Not the file contents). I am on windows 10 and would like to use command line tools.

Here is scenario that may explain the issue.

Folders
-------
source source2 - file_1 - file_1 - file_2 - file_2 - file_3 - file_4 - file_5 - file_5 - file_6 - file_7
Output should be:
-----------------
Source -> Missing files file_4
Source2 -> Missing files file_3 

I did some research, and there are many diff tools, but I am not interested in comparing the file contents. All I want is compare two folders and output which files are missing in both folders (compared to the other one).

I prefer not to use Powershell.

Thank you.

2

4 Answers

robocopy (included in recent Windows versions) can do this in one pass:

given \source\ and \source2\ with some files which are common and files which exist only in either folder, running

robocopy source source2 /L /NJH /NJS /NP /NS

yields

D:\Users\me\test\source\ *EXTRA Datei only_in_source2.txt Neue Datei only_in_source.txt

where lines starting with a * denote files only in source2 (independent of the OS language), and other lines denote files only in source.

The options suppress various output items, and /L takes care that differences are listed only, not copied.

2

This Powershell script does what you want.

$fso = Get-ChildItem -Recurse -path C:\Temp\Source
$fsoBU = Get-ChildItem -Recurse -path C:\Temp\Source2
Compare-Object -ReferenceObject $fso -DifferenceObject $fsoBU

That, and several other options, are discussed here:

2

You can save the next code as ccomp.cmd, and then call it with the /? flag to find out how to use it (tested on Windows 7, Windows 10):

Syntax:

ccomp <dir_tree1> <dir_tree2>

Code:

@echo off
if "!ERRORLEVEL!" == "%ERRORLEVEL%" ( REM if delayed expansion is enabled: ( echo. echo ERROR: This script must be called in a Disabled Delayed Expansion block ^(default^)^^^! echo. call :PressAKey "Press a key to exit..." echo. )>con exit /b 1
)
setlocal disabledelayedexpansion if defined _first_time goto :label1MAIN REM Test CHCP: chcp /?>nul 2>nul||( ( echo. & echo ERROR: Could not start chcp ^(necessary^)! )>con exit /b 1 ) REM Get the initial code page: call :GetCurrentCodePage _initial_CP REM Change the code page (character encoding) for "CON" (console) to 65001 (UTF-8): set _con_error=false mode con cp select=65001>nul 2>nul||( ( echo. & echo WARNING: Could not change the code page for CON ^(Console^)! )>con set _con_error=true ) set _help_flag=0 set /a _count=1 set "_script_path=%~Dpnx0" :repeat1MAIN if _%1_ == _""_ ( REM "%1" is """" set _param%_count%="" shift set /a _count+=1 goto :repeat1MAIN ) else ( if /i "%~1" == "/?" ( set _help_flag=1 shift goto :repeat1MAIN ) else ( if /i "%~1" == "/help" ( set _help_flag=1 shift goto :repeat1MAIN ) else ( if /i "%~1" == "/h" ( set _help_flag=1 shift goto :repeat1MAIN ) else ( if not "%~1" == "" ( REM if "%1" is null, it means that no more parameters are provided set "_param%_count%=%~1" shift set /a _count+=1 goto :repeat1MAIN ) ) ) ) ) set /a _count-=1 set /a _param_count=_count REM start Checking parameters \/ if "%_help_flag%" == "1" ( call :DisplayHelp exit /b 0 ) else ( if %_param_count% gtr 2 ( ( echo. & echo ERROR: Too many parameters! )>con exit /b 1 ) else ( if %_param_count% lss 2 ( ( echo. & echo ERROR: Too few parameters! )>con exit /b 1 ) ) ) set "_error=false" if "%_param1%" == """" ( ( echo. & echo ERROR: First provided directory parameter must not be empty! )>con set "_error=true" ) else ( call :TestIfDirAcccessible _param1 _is_param1_dir setlocal enabledelayedexpansion if not "!_is_param1_dir!" == "0" ( endlocal ( echo. & echo ERROR: First provided directory parameter: "%_param1%" is not a directory or is not accessible! )>con set "_error=true" ) else ( endlocal ) ) if "%_param2%" == """" ( ( echo. & echo ERROR: Second provided directory parameter must not be empty! )>con set "_error=true" ) else ( call :TestIfDirAcccessible _param2 _is_param2_dir setlocal enabledelayedexpansion if not "!_is_param2_dir!" == "0" ( endlocal ( echo. & echo ERROR: Second provided directory parameter "%_param2%" is not a directory or is not accessible! )>con set "_error=true" ) else ( endlocal ) ) call :TestIfPathIsUNC _param1 _result1 call :TestIfPathIsUNC _param2 _result2 if "%_result1%" == "true" ( set "_error=true" ( echo. & echo ERROR: Path1: "%_param1%" seems to be a UNC path ^(contains \\^), and UNC paths are not supported by this program ^(but a UNC path can be mounted ^(for example by using pushd^), in order to make it accessible^)! )>con ) if "%_result2%" == "true" ( set "_error=true" ( echo. & echo ERROR: Path2: "%_param2%" seems to be a UNC path ^(contains \\^), and UNC paths are not supported by this program ^(but a UNC path can be mounted ^(for example by using pushd^), in order to make it accessible^)! )>con ) if "%_error%" == "true" ( ( echo. & call :PressAKey "Press a key to exit!" echo. )>con exit /b 1 ) cmd /u /c ^(echo.^&echo Path1: "%_param1%"^) cmd /u /c ^(echo.^&echo Path2: "%_param2%"^) REM end Checking parameters /\ REM If everything seems ok, proceed to PROCESSING: pushd "%_param1%\">nul set "_param1=%CD%" if "%_param1:~-1%" == "\" set "_param1=%_param1:~0,-1%" popd>nul pushd "%_param2%\">nul set "_param2=%CD%" if "%_param2:~-1%" == "\" set "_param2=%_param2:~0,-1%" popd>nul call :ConvertDriveLetterToUpperCase _param1 _param1 call :ConvertDriveLetterToUpperCase _param2 _param2 call :GetStrLen _param1 _param1_len call :GetStrLen _param2 _param2_len pushd "%_script_path%\..">nul if not defined _first_time ( call :EscapePathString _script_path _script_path_escaped call :EscapePathString _param1 _param1_escaped call :EscapePathString _param2 _param2_escaped ) popd>nul REM Change the code page (character encoding) for "CON" (console) to 437 (ANSI): if "%_con_error%" == "false" ( mode con cp select=437>nul 2>nul )
:label1MAIN REM CHCP 437 = ANSI CODE PAGE REM CHCP 65001 = UTF-8 CODE PAGE if not defined _first_time ( set _first_time=defined chcp 65001>nul cmd /u /c ^(echo.^&echo Start time: %date% %time%^&echo.^) cmd /u /c ^(for /f ^"tokens=^*^" %%l in ^(^'^^^( setlocal^^^&^^^"%%_script_path_escaped%%^^^" ^^^"%%_param1_escaped%%^^^" ^^^"%%_param2_escaped%%^^^"^^^&title Sorting Results ^^^^^^^^^^^^^^^(finally^^^^^^^^^^^^^^^)^^^&endlocal ^^^)^^^|sort^'^) do @^(if not defined _once ^( set "_once=defined"^&echo %%l^) else echo %%l ^)^)^&if defined _once echo. set "_first_time=" set "_second_time=" set "_third_time=" cmd /u /c ^(call echo End time: %%date%% %%time%%^) chcp 437>nul REM Restore the initial code page: chcp %_initial_CP%>nul 2>nul ) else ( if not defined _second_time ( set _second_time=defined ( call :ProcedureAnalyzeFiles ) ) else ( if not defined _third_time ( set "_third_time=defined" ( call :ProcedureProcessFilenamesLengthAndSize1 chcp 65001>nul call :ProcedureProcessFilenamesLengthAndSize2 chcp 437>nul @REM After sorting: "-" is displayed before all other characters: @call echo ----------------------------------------""%%_count1%%"" @title Sorting results. Please wait... ) ) ) )
endlocal & ( if defined _first_time set "_first_time=%_first_time%" if defined _second_time set "_second_time=%_second_time%" if defined _third_time set "_third_time=%_third_time%"
)
goto :eof
REM \\\/// Next subroutines use jeb's syntax for working with delayed expansion: \\\///
:GetStrLen
REM - by jeb - adaptation
( setlocal EnableDelayedExpansion set "s=!%~1!#" set "len=0" for %%P in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do ( if "!s:~%%P,1!" NEQ "" ( set /a "len+=%%P" set "s=!s:~%%P!" ) )
)
( endlocal set "%~2=%len%" exit /b
)
:EscapePathString
( setlocal EnableDelayedExpansion set "string=!%~1!" call :GetStrLen string string_len set /a string_len-=1 for /l %%i in (0,1,!string_len!) do ( rem escape "^", "(", ")", "!", "&" if "!string:~%%i,1!" == "^" ( set "result=!result!^^^^" ) else ( if "!string:~%%i,1!" == "(" ( set "result=!result!^^^(" ) else ( if "!string:~%%i,1!" == ")" ( set "result=!result!^^^)" ) else ( if "!string:~%%i,1!" == "^!" ( set "result=!result!^^^!" ) else ( if "!string:~%%i,1!" == "&" ( set "result=!result!^^^&" ) else ( if "!string:~%%i,1!" == "%%" ( set "result=!result!%%" ) else ( set "result=!result!!string:~%%i,1!" ) ) ) ) ) ) )
)
( endlocal set "%~2=%result%" exit /b
)
:TestIfDirAcccessible
( setlocal EnableDelayedExpansion set _returned_code=0 (pushd "!%~1!">nul 2>nul||set "_returned_code=1")&&popd>nul
)
( endlocal set "%~2=%_returned_code%" exit /b
)
:TestIfPathIsUNC
( setlocal EnableDelayedExpansion set "_current_path=!%~1!" set "_is_unc_path=true" if "!_current_path:\\=!" == "!_current_path!" ( set "_is_unc_path=false" )
)
( endlocal set "%~2=%_is_unc_path%" exit /b
)
:GetCurrentCodePage
( setlocal EnableDelayedExpansion set "_current_cp=-1" for /f "tokens=1,2* delims=:" %%a in ('chcp 2^>nul') do ( set "_current_cp=%%~b" )
)
( endlocal set "%~1=%_current_cp%" exit /b
)
:ConvertDriveLetterToUpperCase
( setlocal EnableDelayedExpansion set "_path=!%~1!" for /f "tokens=1 delims=\" %%f in ('echo "!_path!"') do set "_path_drive=%%~df" set "_upper_drive=!_path_drive!" for %%D in (A: B: C: D: E: F: G: H: I: J: K: L: M: N: O: P: Q: R: S: T: U: V: W: X: Y: Z:) do ( if /i "!_path_drive!" == "%%D" ( set "_upper_drive=%%D" goto :endConvertDriveLetterToUpperCase ) )
)
:endConvertDriveLetterToUpperCase
( endlocal set "%~1=%_upper_drive%%_path:~2%" exit /b
)
REM ///\\\ The subroutines above use jeb's syntax for working with delayed expansion: ///\\\
:GenerateShortName @set "%~1=%~s2"
@goto :eof
:GenerateShortNameSize @set "%~1=%~z2"
@goto :eof
:ProcedureAnalyzeFiles setlocal for /f "tokens=1,2,3,4,5* delims=/" %%p in ('chcp 65001^>nul^&^(setlocal^&^"%_script_path_escaped%^" ^"%_param1_escaped%^" ^"%_param2_escaped%^"^|sort^&endlocal^)^&chcp 437^>nul') do ( if not defined _second_time_for1 ( set /a _total_count=%%~p>nul 2>nul set /a _currrent_count=1 set _second_time_for1=defined ) else ( set /a _current_count+=1 REM START PROCESSING: setlocal enabledelayedexpansion title Analyzing file !_current_count! of !_total_count!... set "_previous_file=!_current_file!" set "_previous_file_type=!_current_file_type!" set "_previous_file_visibility=!_current_file_visibility!" set "_previous_file_dir=!_current_file_dir!" REM Due to a bug in sort, an extra " is added at the end of the line, so we need to remove it: set "_previous_file_size=!_current_file_size:"=!" set "_previous_file_base_dir=!_current_file_base_dir!" setlocal disabledelayedexpansion set "_current_file=%%~p" set "_current_file_type=%%~q" set "_current_file_visibility=%%~r" set "_current_file_dir=%%~s" set "_current_file_size=%%~t" setlocal enabledelayedexpansion if "!_current_file_dir!" == "1" ( endlocal set "_current_file_base_dir=%_param1%" ) else ( if "!_current_file_dir!" == "2" ( endlocal set "_current_file_base_dir=%_param2%" ) else ( endlocal ) ) setlocal enabledelayedexpansion REM Due to a bug in sort, an extra " is added at the end of the line, so we need to remove it: set "_current_file_size=!_current_file_size:"=!" REM if not first time: if NOT "!_previous_file_type!" == "" ( if "!_next!" == "1" ( if "!_current_file_type!" == "!_previous_file_type!" ( if "!_current_file_type!" == "file" ( if NOT "!_current_file!" == "!_previous_file!" ( echo Only in "!_previous_file_dir!" - !_previous_file_type!: "!_previous_file_base_dir!!_previous_file!" ) else ( set "_for_one_cannot_get_size=0" if "!_previous_file_size!" == "-1" set "_for_one_cannot_get_size=1" if "!_current_file_size!" == "-1" set "_for_one_cannot_get_size=1" if "!_for_one_cannot_get_size!" == "0" ( if "!_previous_file_size!" GTR "!_current_file_size!" ( echo "!_previous_file_base_dir!!_previous_file!" ^(!_previous_file_dir!^) size ^(!_previous_file_size!B^) is bigger than "!_current_file_base_dir!!_current_file!" ^(!_current_file_dir!^) size ^(!_current_file_size!B^) ) else ( if "!_previous_file_size!" LSS "!_current_file_size!" ( echo "!_previous_file_base_dir!!_previous_file!" ^(!_previous_file_dir!^) size ^(!_previous_file_size!B^) is smaller than "!_current_file_base_dir!!_current_file!" ^(!_current_file_dir!^) size ^(!_current_file_size!B^) ) ) ) ) ) else ( if NOT "!_current_file!" == "!_previous_file!" ( echo Only in "!_previous_file_dir!" - !_previous_file_type!: "!_previous_file_base_dir!!_previous_file!" ) ) ) else ( echo Only in "!_previous_file_dir!" - !_previous_file_type!: "!_previous_file_base_dir!!_previous_file!" ) ) ) endlocal endlocal endlocal setlocal enabledelayedexpansion if "%%~s" == "1" ( endlocal set "_current_file_base_dir=%_param1%" ) else ( if "%%~s" == "2" ( endlocal set "_current_file_base_dir=%_param2%" ) else ( endlocal ) ) set "_temp=%%~p" setlocal enabledelayedexpansion REM if not first time: if NOT "!_current_file_type!" == "" ( if "!_next!" == "1" ( if "%%~q" == "!_current_file_type!" ( if "!_temp!" == "!_current_file!" ( endlocal set _next=2 ) else ( endlocal set _next=1 ) ) else ( endlocal set _next=1 ) ) else ( endlocal set _next=1 ) ) else ( endlocal set _next=1 ) set "_current_file=%%~p" set "_current_file_type=%%~q" set "_current_file_visibility=%%~r" set "_current_file_dir=%%~s" set "_current_file_size=%%~t" ) ) REM Treat the last file separately: chcp 65001>nul setlocal enabledelayedexpansion if "!_next!" == "1" ( echo Only in "!_current_file_dir!" - !_current_file_type!: "!_current_file_base_dir!!_current_file!" ) endlocal chcp 437>nul endlocal
goto :eof
:ProcedureProcessFilenamesLengthAndSize1 @setlocal @set /a _count1=0 @REM Process directories: @chcp 65001>nul @title Loading directory paths for directory 1. Please wait... @pushd "%_param1%">nul @for /r /d %%f in (*) do @( @set "_current_path=%%~f" @if "%%~zf" == "" ( @call :GenerateShortName _short_name "%%~f" @call :GenerateShortNameSize _size "%%_short_name%%" ) @set /a _count1+=1 >nul @setlocal enabledelayedexpansion @title Processing file !_count1!... @if not "%%~zf" == "" ( @echo "!_current_path:~%_param1_len%!///dir///1///1///%%~zf" ) else ( @if not "!_size!" == "" ( @echo "!_current_path:~%_param1_len%!///dir///1///1///!_size!" ) else ( @echo "!_current_path:~%_param1_len%!///dir///1///1///-1" ) ) @endlocal ) @popd>nul @title Please wait... @REM Process directories: @title Loading directory paths for directory 2. Please wait... @pushd "%_param2%">nul @for /r /d %%f in (*) do @( @set "_current_path=%%~f" @if "%%~zf" == "" ( @call :GenerateShortName _short_name "%%~f" @call :GenerateShortNameSize _size "%%_short_name%%" ) @set /a _count1+=1 >nul @setlocal enabledelayedexpansion @title Processing file !_count1!... @if not "%%~zf" == "" ( @echo "!_current_path:~%_param2_len%!///dir///1///2///%%~zf" ) else ( @if not "!_size!" == "" ( @echo "!_current_path:~%_param2_len%!///dir///1///2///!_size!" ) else ( @echo "!_current_path:~%_param2_len%!///dir///1///2///-1" ) ) @endlocal ) @popd>nul @title Please wait... @REM Process files: @title Loading file paths for directory 1. Please wait... @pushd "%_param1%">nul @for /r %%f in (*) do @( @set "_current_path=%%~f" @if "%%~zf" == "" ( @call :GenerateShortName _short_name "%%~f" @call :GenerateShortNameSize _size "%%_short_name%%" ) @set /a _count1+=1 >nul @setlocal enabledelayedexpansion @title Processing file !_count1!... @if not "%%~zf" == "" ( @echo "!_current_path:~%_param1_len%!///file///1///1///%%~zf" ) else ( @if not "!_size!" == "" ( @echo "!_current_path:~%_param1_len%!///file///1///1///!_size!" ) else ( @echo "!_current_path:~%_param1_len%!///file///1///1///-1" ) ) @endlocal ) @popd>nul @title Please wait... @REM Process files: @title Loading file paths for directory 2. Please wait... @pushd "%_param2%">nul @for /r %%f in (*) do @( @set "_current_path=%%~f" @if "%%~zf" == "" ( @call :GenerateShortName _short_name "%%~f" @call :GenerateShortNameSize _size "%%_short_name%%" ) @set /a _count1+=1 >nul @setlocal enabledelayedexpansion @title Processing file !_count1!... @if not "%%~zf" == "" ( @echo "!_current_path:~%_param2_len%!///file///1///2///%%~zf" ) else ( @if not "!_size!" == "" ( @echo "!_current_path:~%_param2_len%!///file///1///2///!_size!" ) else ( @echo "!_current_path:~%_param2_len%!///file///1///2///-1" ) ) @endlocal ) @popd>nul @title Please wait... @chcp 437>nul @endlocal & ( @set _count1=%_count1% )
@goto :eof
:ProcedureProcessFilenamesLengthAndSize2 @setlocal @REM Process hidden directories: @for /f "tokens=*" %%f in ('title Loading hidden directory paths for directory 1. Please wait...^&@pushd "%_param1%"^>nul^&^&dir /a:dh /s /b 2^>nul^&^&popd^>nul^&title Please wait...') do @( @set "_current_path=%%~f" @if "%%~zf" == "" ( @call :GenerateShortName _short_name "%%~f" @call :GenerateShortNameSize _size "%%_short_name%%" ) @set /a _count1+=1 >nul @setlocal enabledelayedexpansion @title Processing file !_count1!... @if not "%%~zf" == "" ( @echo "!_current_path:~%_param1_len%!///dir///0///1///%%~zf" ) else ( @if not "!_size!" == "" ( @echo "!_current_path:~%_param1_len%!///dir///0///1///!_size!" ) else ( @REM This file is hidden and probably has a Unicode path: @echo "!_current_path:~%_param1_len%!///dir///0///1///-1" ) ) @endlocal ) @title Please wait... @REM Process hidden directories: @for /f "tokens=*" %%f in ('title Loading hidden directory paths for directory 2. Please wait...^&@pushd "%_param2%"^>nul^&^&dir /a:dh /s /b 2^>nul^&^&popd^>nul^&title Please wait...') do @( @set "_current_path=%%~f" @if "%%~zf" == "" ( @call :GenerateShortName _short_name "%%~f" @call :GenerateShortNameSize _size "%%_short_name%%" ) @set /a _count1+=1 >nul @setlocal enabledelayedexpansion @set /a _count1+=1 >nul @title Processing file !_count1!... @if not "%%~zf" == "" ( @echo "!_current_path:~%_param2_len%!///dir///0///2///%%~zf" ) else ( @if not "!_size!" == "" ( @echo "!_current_path:~%_param2_len%!///dir///0///2///!_size!" ) else ( @REM This file is hidden and probably has a Unicode path: @echo "!_current_path:~%_param2_len%!///dir///0///2///-1" ) ) @endlocal ) @title Please wait... @REM Process hidden files: @for /f "tokens=*" %%f in ('title Loading hidden file paths for directory 1. Please wait...^&@pushd "%_param1%"^>nul^&^&dir /a:-dh /s /b 2^>nul^&^&popd^>nul^&title Please wait...') do @( @set "_current_path=%%~f" @if "%%~zf" == "" ( @call :GenerateShortName _short_name "%%~f" @call :GenerateShortNameSize _size "%%_short_name%%" ) @set /a _count1+=1 >nul @setlocal enabledelayedexpansion @title Processing file !_count1!... @if not "%%~zf" == "" ( @echo "!_current_path:~%_param1_len%!///file///0///1///%%~zf" ) else ( @if not "!_size!" == "" ( @echo "!_current_path:~%_param1_len%!///file///0///1///!_size!" ) else ( @REM This file is hidden and probably has a Unicode path: @echo "!_current_path:~%_param1_len%!///file///0///1///-1" ) ) @endlocal ) @title Please wait... @REM Process hidden files: @for /f "tokens=*" %%f in ('title Loading hidden file paths for directory 2. Please wait...^&@pushd "%_param2%"^>nul^&^&dir /a:-dh /s /b 2^>nul^&^&popd^>nul^&title Please wait...') do @( @set "_current_path=%%~f" @set /a _count1+=1 >nul @if "%%~zf" == "" ( @call :GenerateShortName _short_name "%%~f" @call :GenerateShortNameSize _size "%%_short_name%%" ) @setlocal enabledelayedexpansion @title Processing file !_count1!... @if not "%%~zf" == "" ( @echo "!_current_path:~%_param2_len%!///file///0///2///%%~zf" ) else ( @if not "!_size!" == "" ( @echo "!_current_path:~%_param2_len%!///file///0///2///!_size!" ) else ( @REM This file is hidden and probably has a Unicode path: @echo "!_current_path:~%_param2_len%!///file///0///2///-1" ) ) @endlocal ) @title Please wait... @endlocal & ( @set _count1=%_count1% )
@goto :eof
:DisplayHelp echo. echo %~n0 ^(Cmd COMPare^) - Compare two directory trees by file and folder paths and by size echo. echo Syntax: %~n0 ^<dir_tree1^> ^<dir_tree2^> echo. echo - where ^<dir_tree1^> and ^<dir_tree2^> are two directory trees to be compared, provided by the user echo. echo * Note 1: echo - Files that are hidden and also have a Unicode path - are compared only by path, not also by size echo - In some rare cases ^(for some Unicode file paths^) some files may be misreported echo. echo * Note 2: echo - This program uses the ^"sort^" utility for sorting results, so the waiting time for the comparison of the two directories depends on (is a multiple of) n * log n ^(the time complexity for the quick sort algorithm ^(used in ^"sort^"^)^) - where - n is the total number of files in the two directories that are to be compared. echo - The output of the program is Unicode
goto :eof
:PressAKey set /p=%~1<nul pause>nul
goto :eof
2

Do a dir /b /A-dof both folders to a file and compare these with findstr and the /VG: options

Given a sample tree:

> tree /f
X:.
│
└───Folders ├───source │ file_1 │ file_2 │ file_3 │ file_5 │ file_6 │ └───source2 file_1 file_2 file_4 file_5 file_7

The following batch file:

:: Q:\Test\2019\02\19\SU_1407481.cmd
@echo off
Set "DirA=X:\Folders\source\"
Set "DirB=X:\Folders\source2\"
Dir /B /A-D "%DirA%*" >DirA.txt
Dir /B /A-D "%DirB%*" >DirB.txt
echo file(s) missing in %DirA%
findstr /VG:DirA.txt DirB.txt
echo fil(e) missing in %DirB%
findstr /VG:DirB.txt DirA.txt

yields this output:

> SU_1407481.cmd
file(s) missing in X:\Folders\source\
file_4
file_7
file(s) missing in X:\Folders\source2\
file_3
file_6

You Might Also Like