I have two folders that contain all the same files and subfolders, but the conents inside each file may have changed. I want to write a batch file that will search through each
Here is another way to accomplish the task. Set the variables Folder1 and Folder2 to the full path of the folders you want to compare and run the batch file.
Output:
Dup – the file exists in both folders and are identical.
Dif - the file exists in both folders but the content of the files are different.
New – The file exists in one folder but not the other.
@Echo Off
SetLocal EnableDelayedExpansion
Set "Folder1=%UserProfile%\Desktop\Test Folder1"
Set "Folder2=%UserProfile%\Desktop\Test Folder2"
For /R "%Folder1%" %%x In (*.*) Do (
Set "FullPath=%%x"
Set "RelPath=!FullPath:%Folder1%=!"
If Exist "%Folder2%!RelPath!" (
>Nul 2>&1 FC /b "%Folder1%!RelPath!" "%Folder2%!RelPath!" && (
Echo Dup - %%x
)||(
Echo Dif - %%x
)
) Else (
Echo New - %%x
)
)
For /R "%Folder2%" %%x In (*.*) Do (
Set "FullPath=%%x"
Set "RelPath=!FullPath:%Folder2%=!"
If Not Exist "%Folder1%!RelPath!" (
Echo New - %%x
)
)
I'm having better luck with the following batch file. The path names have to completely match though; so only the Drive Letter differs.
Mapping a shared network folder may make this easier. I can't say for sure for your case.
'--- setlocal set "folder1=D:\User\Public" set "Drv2=E:" set "fileMask=*"
setlocal
set "folder1=<DrvLttr>:\<Folder>\<SubFolder>"
set "Drv2=<DrvLttr2>:"
set "LogFile=<SystemDrv>\User\<UserName>\<LogFileName>"
ECHO "the '>' may OVER WRITE or make a ~NEW~ File for the results" > "%LogFile%"
ECHO " '>>' adds to the end of the file >> "%LogFile%"
FOR /R %folder1% %%A in ( *.* ) DO FC "%%A" "%Drv2%%%~pnxA" 1>> "%LogFile%" 2>&1
If you wish to note what is going to be the command for testing, you can try inserting ECHO after DO. You can drop the 1>>... stuff to see the result on screen, instead of having to open the output file.
No need for a batch file. A single FC command can do what you want:
fc folder1\* folder2\*
You can be more specific for the file mask in the first folder if you want. For example folder1\*.txt
.
The command will report on files that exist in folder1 but are missing in folder2. Extra files in folder2 are simply ignored.
There are a number of options to the FC command. Enter HELP FC
or FC /?
from the command prompt to get more information.
EDIT
Extending the solution to support subfolders is a bit tricky. It is easy to iterate the folder hierarchy for a given root using FOR /R. The problem is getting the relative paths so that the hierarchy can be applied to another root.
The simplest solution is to use FORFILES instead, since it directly supports relative paths. but FORFILES is... S L O W :/
At this point, a batch file makes sense:
@echo off
setlocal
set "folder1=c:\path\To\Folder1\Root"
set "folder2=d:\path\To\Folder2\Root"
set "fileMask=*"
for /f "delims=" %%F in (
'echo "."^&forfiles /s /p "%folder1%" /m "%fileMask%" /c "cmd /c if @isdir==TRUE echo @relpath"'
) do fc "%folder1%\%%~F\%fileMask%" "%folder2%\%%~F\*"
I modified a batch file I wrote for a CD process that should meet your need. It
If both directory structures are under the same parent, then all you need to do is update the first 8 variables in the script. If the directory trees have different parents, then read through the scripts comments. Particularly lines 14, 38 and 46.
:: This script compares the contents of 2 trees
:: set a workspace location for the script outside of the trees being reviewed
set home=D:\path\to\batch_file_home
set Input=D:\path\to\batch_file_home\Input_Files
set Resource=D:\path\to\batch_file_home\Resource_Files
set Output=D:\path\to\where your want to view your\Output_Files
set environment=D:\path\to\parent directory containing the different tree structures (if they do not share a parent, then make this the drive)
:: the next 3 lines are only needed if you want to predefine multiple directories for comparison
set Prod=production
set QA=test
set Dev=branches\dev
:: If you remove the 3 lines above, then you need to replace the 2 below variables with values
:: If the trees are not under the same parent, then include the full path for Tree A and B below
set Tree_A=%Prod%
set Tree_B=%QA%
:: if you already have an object list, place it in the Input folder and remove lines 24 through 35 of this script
set Object_List=Object_List_minus_Direcotries.txt
set Output_File=File_differences.txt
if exist %Output%\%Output_File% del %Output%\%Output_File%
if exist %Output%\Differences\*.txt del %Output%\Differences\*.txt
if exist %Resource%\* del /q %Resource%\*
:: since you state the objects in both trees are always the same, I have not included a comparison to verify the 2 trees match
:: this section identifies the contents of Tree A
cd %environment%\%Tree_A%
dir /b /s > %Resource%\Complete_Tree_A_Object_List.txt
:: Next, remove the objects that are directories
setlocal enabledelayedexpansion
for /f "tokens=*" %%p in (%Resource%\Complete_Tree_A_Object_List.txt) do (
dir /a:d /b %%p 2>nul >nul && (set object_type=folder) || (set object_type=file)
echo !object_type!
if !object_type!==file echo %%p >> %Resource%\%Object_List%
)
:: in the object list, remove the parent tree from the path
:: if the Trees are not under the same parent, then comment out the below 6 lines
powershell -command "(Get-Content %Resource%\%Object_List%) -replace '\\','/' | set-content %Resource%\%Object_List%"
powershell -command "(get-content %Resource%\%Object_List%) | Foreach {$_.TrimEnd()} | Set-Content %Resource%\%Object_List%"
set remove_parent_prefix=%environment%\%Tree_A%
set remove_parent_prefix=%remove_parent_prefix:\=/%
powershell -command "(Get-Content %Resource%\%Object_List%) -replace '%remove_parent_prefix%/','' | set-content %Resource%\%Object_List%"
powershell -command "(Get-Content %Resource%\%Object_List%) -replace '/','\' | set-content %Resource%\%Object_List%"
:: the below loop assumes both Trees are under the same parent. If this is not the case, replace the cd %environment% line with cd %home%
:: when the Trees are not under the same parent, set home to the root location, example cd D:\
setlocal enabledelayedexpansion
for /f "tokens=*" %%x in (%Resource%\%Object_List%) do (
set Diff_File=%%x
set Diff_File=!Diff_File:\=-!
cd %environment%
fc %Tree_A%\%%x %Tree_B%\%%x > "%Output%\Differences\!Diff_File!-%Output_File%"
for %%a in ("%Output%\Differences\!Diff_File!-%Output_File%") do for /f %%b in ('find /c /v "" ^< "%%a" ') do if %%b LSS 3 del "%%a"
for %%R in ("%Output%\Differences\!Diff_File!-%Output_File%") do if not %%~zR lss 1 (
echo %%x >> %Output%\%Output_File%
)
for %%R in ("%Output%\Differences\!Diff_File!-%Output_File%") do if %%~zR lss 1 (
del "%Output%\Differences\!Diff_File!-%Output_File%"
)
)
endlocal
:: Clean up Resources. If you want to review the temp files used to create the report, comment out the below line
if exist %Resource%\* del /q %Resource%\*