How to Compare and Merge Two Text Files in Batch Script
Working with multiple data sources often requires reconciling their contents. You may need to verify that a configuration file hasn't changed, extract only the new entries from a daily log, or combine several fragmented user lists into a single master file.
In this guide, we will demonstrate how to compare and merge text files natively using fc, findstr, type, and PowerShell.
Method 1: Analyzing Differences with fc (File Compare)
The fc (File Compare) command is the native Windows tool for identifying the differences between two files. It outputs the exact lines where the files diverge and provides reliable exit codes to script against.
@echo off
setlocal enabledelayedexpansion
set "File1=old_config.txt"
set "File2=new_config.txt"
:: Verify both files exist
if not exist "%File1%" (
echo [ERROR] "%File1%" missing.
pause
exit /b 1
)
if not exist "%File2%" (
echo [ERROR] "%File2%" missing.
pause
exit /b 1
)
echo Comparing %File1% and %File2%...
echo ------------------------------------------
:: /N displays the line numbers during the comparison
:: /C ignores case during the comparison
:: /W compresses whitespace (tabs and spaces)
fc /N /C "%File1%" "%File2%"
:: Capture the exit code immediately
set "fcResult=!errorlevel!"
echo ------------------------------------------
:: Check the exit code
:: 0 = Files are identical
:: 1 = Files are different
:: 2 = Cannot find one of the files / syntax error
if !fcResult! equ 0 (
echo [RESULT] The files are completely identical.
) else if !fcResult! equ 1 (
echo [RESULT] Differences were found.
) else (
echo [ERROR] Comparison failed.
)
endlocal
pause
exit /b 0
fc is excellent for visual review or simple boolean checks (e.g., "did this file change?"), but its verbose output format is difficult to parse if you want to use the actual differences programmatically in the rest of your script.
Method 2: Finding Net Additions with findstr
If you want to know "Which lines are in File B that are NOT in File A?", you can use findstr as a set-difference tool. This is extremely useful for extracting only the newest entries from a cumulative log file.
@echo off
setlocal enabledelayedexpansion
set "OldList=yesterday_users.txt"
set "NewList=today_users.txt"
set "AddedUsers=new_users.txt"
if not exist "%OldList%" (
echo [ERROR] "%OldList%" missing.
pause
exit /b 1
)
if not exist "%NewList%" (
echo [ERROR] "%NewList%" missing.
pause
exit /b 1
)
echo Finding new entries in %NewList%...
:: /L reads search strings literally (not as regular expressions)
:: /X requires lines to match exactly in their entirety
:: /V prints only lines that do NOT match
:: /G reads the search strings from the specified file
findstr /L /X /V /G:"%OldList%" "%NewList%" > "%AddedUsers%"
:: Capture the exit code immediately
set "findResult=!errorlevel!"
:: findstr returns 0 if matches were found (lines that do NOT appear in OldList)
:: findstr returns 1 if no matches were found (all lines already exist in OldList)
:: findstr returns 2 if a file error or syntax error occurred
if !findResult! equ 2 (
echo [ERROR] File processing failed.
pause
exit /b 1
)
if !findResult! equ 1 (
echo [INFO] No new additions found. All entries already exist in "%OldList%".
) else (
echo [SUCCESS] New additions saved to "%AddedUsers%".
)
endlocal
pause
exit /b 0
This method dynamically treats the entire %OldList% as a database of literal match strings. It effectively subtracts the contents of the old list from the new list.
Method 3: Sequential Merging (type)
To combine two or more text files sequentially (File B appended to the bottom of File A), manipulating redirection with the type command is the safest approach.
@echo off
setlocal
set "File1=part1.log"
set "File2=part2.log"
set "Merged=combined.log"
if not exist "%File1%" (
echo [ERROR] "%File1%" missing.
pause
exit /b 1
)
if not exist "%File2%" (
echo [ERROR] "%File2%" missing.
pause
exit /b 1
)
echo Merging files...
:: 1. Output the first file into a clean target file
type "%File1%" > "%Merged%"
:: 2. Inject a blank line
:: This protects against the first file lacking a trailing newline,
:: which would cause the files to merge on the exact same line.
echo.>> "%Merged%"
:: 3. Append the second file to the target file
type "%File2%" >> "%Merged%"
echo [SUCCESS] Files merged cleanly into "%Merged%".
endlocal
pause
exit /b 0
Method 4: Merging Without Duplicates (PowerShell Bridge)
If you are joining two independent lists (like server inventories) and want a unified, alphabetically sorted master list with no duplicate entries, PowerShell provides a robust, single-pass pipeline.
@echo off
setlocal enabledelayedexpansion
set "ListA=server_group_a.txt"
set "ListB=server_group_b.txt"
set "MergedUnique=all_servers_unique.txt"
if not exist "%ListA%" (
echo [ERROR] "%ListA%" missing.
pause
exit /b 1
)
if not exist "%ListB%" (
echo [ERROR] "%ListB%" missing.
pause
exit /b 1
)
echo Merging and deduplicating files...
:: Read both files, sort them, and keep only the unique lines
powershell -NoProfile -Command ^
"Get-Content -Path '%ListA%', '%ListB%' | " ^
"Sort-Object -Unique | " ^
"Set-Content -Path '%MergedUnique%' -Encoding UTF8"
:: Capture the exit code immediately
set "psResult=!errorlevel!"
if !psResult! equ 0 (
echo [SUCCESS] Unified, unique list saved to "%MergedUnique%".
) else (
echo [ERROR] PowerShell merge failed.
pause
exit /b 1
)
endlocal
pause
exit /b 0
Best Practices
- Verify Source Files: Always check that input files exist before processing. Missing files can cause
fc,findstr, or PowerShell to fail or produce garbage output. - Beware the Missing Newline: When using
copy /bor raw>>redirection to concatenate files in native Batch, the first line of the second file will append directly to the last line of the first file if the first file doesn't end with a carriage return. Using the injectedecho.(Method 3) prevents this silent formatting corruption. - Encoding Compatibility: The native legacy commands (
fc,findstr,type) work best with standard ANSI/ASCII files or UTF-8 files without a BOM. Comparing or searching UTF-16 files (often generated by native PowerShell cmdlets without explicit encoding) usingfcorfindstrcan produce completely broken results. Always be aware of your file encodings. - Case Sensitivity:
fcis case-sensitive by default (use/Cto ignore case).findstris case-sensitive (use/Ito ignore case, though/Xexact matches behave best when case-matched).Sort-Object -Uniquein PowerShell is case-insensitive by default (use-CaseSensitiveinside the cmdlet call to strictly match case). Choose the tool that best fits your data's casing guidelines.
Conclusion
Comparing and merging files are foundational operations for reconciling data from multiple sources. Whether you are generating a "diff" report with fc, subtracting old data sets from new ones with findstr, safely stacking logs with type, or building a unified, deduplicated master list via PowerShell, these techniques allow your scripts to consolidate information securely and efficiently.