How to Compare Two Directories for Differences in Batch Script
When managing backups, synchronizing development folders, or analyzing structural changes, you often need to compare the contents of two directories. You might want to know if a file is missing in the backup, if a modified version exists, or if there are entirely new subfolders.
In this guide, we will explore the different ways to compare two directories using Batch Script. We will start with a basic FC (File Compare) approach and move to the incredibly robust Robocopy tool, which is the industry standard for directory analysis.
Method 1: Using FC (File Compare) inside a Loop
If you simply want to iterate through Directory A and check if each file exists in Directory B, and if they are identical byte-for-byte, you can use a FOR loop combined with the FC command.
This method is slow for large directories and does not check for files that exist in B but are missing in A.
@echo off
setlocal EnableDelayedExpansion
set "DIR_A=C:\Project\Source"
set "DIR_B=D:\Backup\Source"
if not exist "%DIR_A%\" (
echo [ERROR] Source directory not found: %DIR_A%
pause
exit /b 1
)
if not exist "%DIR_B%\" (
echo [ERROR] Comparison directory not found: %DIR_B%
pause
exit /b 1
)
echo Comparing %DIR_A% with %DIR_B%
echo ==============================================
set "FILE_COUNT=0"
REM Iterate through all files in Directory A
for %%F in ("%DIR_A%\*") do (
set /a "FILE_COUNT+=1"
REM Check if the file exists in Directory B
if exist "%DIR_B%\%%~nxF" (
REM If it exists, compare the contents
REM /b performs a binary comparison (faster and stricter)
fc /b "%%F" "%DIR_B%\%%~nxF" >nul 2>nul
if !ERRORLEVEL! neq 0 (
echo [DIFFERENT] %%~nxF
) else (
echo [MATCH] %%~nxF
)
) else (
echo [MISSING] %%~nxF (not in B)^
)
)
if !FILE_COUNT! equ 0 (
echo No files found in %DIR_A%.
)
echo ==============================================
echo Done basic comparison.
endlocal
pause
Limitations of this Method
- Speed:
FC /breads every byte of the file. If you have 50GB of video files, this script will run for hours. - One-Directional: It doesn't tell you if
DIR_Bcontains extra files not present inDIR_A. - No Subdirectories: To handle subdirectories, you would need complex recursive loops (
for /R).
Method 2: Using Robocopy in "List Only" Mode (Recommended)
Robocopy (Robust File Copy) is a built-in Windows tool renowned for mirroring and copying massive directories. However, it possesses a brilliant hidden feature: the /L switch ("List Only").
When you use /L, Robocopy simulates the copy. It compares the two directories, evaluates timestamps, sizes, and attributes, and tells you exactly what would happen if you mirrored them. It is blindingly fast because it only checks metadata, not the binary contents.
The Ultimate Comparison Script
Here is how you use Robocopy /L to quickly identify missing, newer, and older files between two folder structures.
@echo off
setlocal
set "SOURCE_DIR=C:\Project\Prod"
set "DEST_DIR=C:\Project\Backup"
set "LOG_DIR=C:\Temp"
set "LOG_FILE=%LOG_DIR%\CompareLog.txt"
if not exist "%SOURCE_DIR%\" (
echo [ERROR] Source directory not found: %SOURCE_DIR%
pause
exit /b 1
)
if not exist "%DEST_DIR%\" (
echo [ERROR] Destination directory not found: %DEST_DIR%
pause
exit /b 1
)
REM Ensure the log directory exists
if not exist "%LOG_DIR%\" mkdir "%LOG_DIR%"
echo Analyzing differences using Robocopy (Simulation Mode^)...
echo Source: %SOURCE_DIR%
echo Dest: %DEST_DIR%
echo.
REM /L : List only (don't copy anything)
REM /S : Include subdirectories (excluding empty ones)
REM /BYTES : Show exact sizes
REM /FP : Include full path names
REM /NDL : No Directory List (Focus only on files)
REM /NP : No Progress (removes the %% counter)
REM /NJH : No Job Header
REM /NJS : No Job Summary
robocopy "%SOURCE_DIR%" "%DEST_DIR%" /L /S /BYTES /FP /NDL /NP /NJH /NJS > "%LOG_FILE%"
echo Analysis complete. Reviewing differences...
echo ----------------------------------------------------
echo ---- FILES NEWER IN SOURCE OR MISSING IN DEST ----
findstr /i /c:"Newer" /c:"New File" /c:"Older" "%LOG_FILE%"
echo.
echo ---- EXTRA FILES IN DEST (NOT IN SOURCE) ----
findstr /i /c:"*EXTRA" "%LOG_FILE%"
echo.
echo ----------------------------------------------------
echo Detailed breakdown available in %LOG_FILE%
endlocal
pause
Understanding the Robocopy Log Output
When analyzing the CompareLog.txt, Robocopy classifies files beautifully:
- New File: Exists in Source, missing in Dest.
- Newer: Exists in both, but Source is more recently modified.
- Older: Exists in both, but Source is older than Dest.
- *EXTRA File: Exists in Dest, but missing in Source. (If you ran a
/MIRcopy, these would be deleted). - Same: Identical size, timestamp, and attributes (Usually hidden by default summary, but visible if checking the full verbose log).
Advantages of the Robocopy Approach
- Speed: It can compare hundreds of thousands of files across deep subdirectories in seconds.
- Bi-directional analysis: It natively detects "EXTRA" files in the destination.
- Comprehensive: It analyzes timestamps and sizes simultaneously.
Method 3: PowerShell Integration for File Hashing
If metadata (timestamps/sizes) isn't enough, and you must guarantee two directories are identical byte-for-byte (e.g., verifying a highly secure data transfer), but FC is too slow or clunky, you can wrap PowerShell's Get-FileHash cmdlet in your batch script.
This is processor-intensive but mathematically conclusive.
@echo off
setlocal
set "DIR_A=C:\SecureFiles"
set "DIR_B=D:\VerifyTransfer"
if not exist "%DIR_A%\" (
echo [ERROR] Directory not found: %DIR_A%
pause
exit /b 1
)
if not exist "%DIR_B%\" (
echo [ERROR] Directory not found: %DIR_B%
pause
exit /b 1
)
echo Hashing and comparing %DIR_A% with %DIR_B%...
echo This may take a long time for large directories.
echo.
powershell -NoProfile -Command ^
"try {" ^
"$filesA = Get-ChildItem -LiteralPath '%DIR_A%' -File -Recurse -ErrorAction Stop | Get-FileHash;" ^
"$filesB = Get-ChildItem -LiteralPath '%DIR_B%' -File -Recurse -ErrorAction Stop | Get-FileHash;" ^
"$diff = Compare-Object $filesA $filesB -Property Hash, Name;" ^
"if ($diff) {" ^
"$diff | Format-Table Name, Hash, @{N='Status';E={if($_.SideIndicator -eq '<='){'Only/Different in A'}else{'Only/Different in B'}}} -AutoSize" ^
"} else {" ^
"Write-Host 'All files match. Directories are identical.' -ForegroundColor Green" ^
"}" ^
"} catch {" ^
"Write-Host ('[ERROR] ' + $_.Exception.Message)" ^
"}"
endlocal
pause
Summary
When comparing directories in a Batch script:
- Never try to write complex recursive
FCloops unless forced. - Always use
Robocopy /Lfor standard IT administrative tasks. It is incredibly fast, built-in, handles subdirectories natively, and tells you exactly which files differ based on their metadata. - Offload to PowerShell (
Get-FileHash) if you require cryptographic guarantees that two directory trees are identical byte-for-byte.