(view source code of dircomp.bat as plain text)
@ECHO OFF
:: Check Windows version
IF NOT "%OS%"=="Windows_NT" GOTO Syntax
:: Only /DEBUG is valid as optional third argument
IF NOT "%~3"=="" IF /I NOT "%~3"=="/C" IF /I NOT "%~3"=="/DEBUG" GOTO Syntax
:: Two command line arguments are mandatory
IF "%~1"=="" GOTO Syntax
IF "%~2"=="" GOTO Syntax
:: If the first argument is not a folder, it should end with \*.ext"
IF NOT "%~x1"=="" (
ECHO "%~1"| FINDSTR /R /E /I /C:"\\\*\%~x1." >NUL || GOTO Syntax
)
:: Initial check if (files and) folders exist
IF NOT EXIST "%~1" GOTO Syntax
IF NOT EXIST "%~2" GOTO Syntax
SETLOCAL ENABLEDELAYEDEXPANSION
:: Reset the variables we are going to use
SET AllFiles1=
SET AllFiles2=
SET Dir1=
SET Dir2=
SET FileSpec1=
SET FileSpec2=
SET FileType=*.*
SET NumFiles1=0
SET NumFiles2=0
SET TotalFiles1=
SET TotalFiles2=
SET TotalLine1=
SET TotalLine2=
SET TotalSize1=
SET TotalSize2=
SET Type=
:: Check if FCIV is available, and if not, prompt to open its download page
:: Code corrected in version 3.10, as the earlier versions failed to detect
:: the absence of FCIV.EXE (thanks Ron Guggisberg for finding this bug)
ECHO Checking availability of FCIV utility . . .
SET Answer=
FCIV.EXE -h >NUL 2>&1
IF ERRORLEVEL 1 (
ECHO This batch file requires Microsoft's File Checksum Integrity Verifier utility
ECHO ^(FCIV.EXE^), available at http://support.microsoft.com/kb/841290
ECHO.
SET Answer=N
SET /P Answer=Do you want to open the download page now? [y/N]
IF /I NOT "!Answer!"=="Y" GOTO Syntax
CLS
ECHO.
ECHO You are about to open Microsoft's FCIV download page.
ECHO Download and install FCIV.EXE and restart this batch file.
ECHO.
PAUSE
START http://support.microsoft.com/kb/841290
ENDLOCAL
GOTO:EOF
)
IF NOT "%~nx1"=="" (
SET FileType=*%~x1
SET Type=-type *%~x1
)
:: Quick and dirty way to check if directories exist and handle trailing backslashes in one go
PUSHD "%~dp1"
IF ERRORLEVEL 1 (
ENDLOCAL
GOTO Syntax
) ELSE (
CD | FIND "&" >NUL
IF ERRORLEVEL 1 (
SET AllFiles1="!__CD__!*.*"
SET Dir1="!CD!"
SET FileSpec1="!__CD__!%FileType%"
POPD
) ELSE (
POPD
GOTO Syntax
)
)
PUSHD "%~f2"
IF ERRORLEVEL 1 (
ENDLOCAL
GOTO Syntax
) ELSE (
CD | FIND "&" >NUL
IF ERRORLEVEL 1 (
SET AllFiles2="!__CD__!*.*"
SET Dir2="!CD!"
SET FileSpec2="!__CD__!%FileType%"
POPD
) ELSE (
POPD
GOTO Syntax
)
)
:: :: :: :: :: :: :: :: :: :: :: :: :: :: ::
:: ::
:: Part I: just check the total file size ::
:: ::
:: :: :: :: :: :: :: :: :: :: :: :: :: :: ::
ECHO Checking number of files and total file size for both directories . . .
:: Get number of matching files and total file size for first directory
FOR /F %%A IN ('DIR "%~1" /S ^| FIND /C "("') DO SET /A TotalLine1 = %%A - 1
FOR /F "tokens=2,4" %%A IN ('DIR "%~1" /-C /S ^| FIND "(" ^| FIND /N "(" ^| FIND "[%TotalLine1%]"') DO (
SET TotalFiles1=%%A
SET TotalSize1=%%B
)
:: Get number of matching files and total file size for second directory
FOR /F %%A IN ('DIR "%FileSpec2%" /S ^| FIND /C "("') DO SET /A TotalLine2 = %%A - 1
FOR /F "tokens=2,4" %%A IN ('DIR %FileSpec2% /-C /S ^| FIND "(" ^| FIND /N "(" ^| FIND "[%TotalLine2%]"') DO (
SET TotalFiles2=%%A
SET TotalSize2=%%B
)
:: Abort if the NUMBER of matching files does not match
IF NOT %TotalFiles1% EQU %TotalFiles2% (
ECHO Number of files is different:
ECHO %TotalFiles1% files in %Dir1%
ECHO %TotalFiles2% files in %Dir2%
ECHO.
ECHO Aborting comparison . . .
ECHO.
ENDLOCAL
EXIT /B 2
)
:: Warn if the TOTAL SIZE of the files does not match
IF NOT %TotalSize1% EQU %TotalSize2% (
ECHO Total file size is different:
ECHO %TotalSize1% bytes in %Dir1%
ECHO %TotalSize2% bytes in %Dir2%
ECHO.
IF /I "%~3"=="/C" (
ECHO Continuing comparison . . .
ECHO.
) ELSE (
ECHO Aborting comparison . . .
ECHO.
ENDLOCAL
EXIT /B 2
)
)
:: :: :: :: :: :: :: :: :: :: :: :: ::
:: ::
:: Part II: compare file timestamps ::
:: ::
:: :: :: :: :: :: :: :: :: :: :: :: ::
ECHO Comparing files' timestamps for both directories . . .
:: XCOPY /D /Y /L just checks what is newer without actually copying anything
FOR /F %%A IN ('XCOPY %FileSpec1% %AllFiles2% /S /D /H /R /Y /L 2^>NUL') DO SET NumFiles1=%%A
FOR /F %%A IN ('XCOPY %FileSpec2% %AllFiles1% /S /D /H /R /Y /L 2^>NUL') DO SET NumFiles2=%%A
IF %NumFiles1% EQU 0 IF %NumFiles2% EQU 0 (
REM Do nothing if all timestamps match
) ELSE (
IF %NumFiles2% GTR 0 ECHO %NumFiles2% files in %Dir1% are older
IF %NumFiles1% GTR 0 ECHO %NumFiles1% files in %Dir2% are older
)
:: :: :: :: :: :: :: :: :: :: :: :: :: :: ::
:: ::
:: Part III: compare checksums per file ::
:: ::
:: :: :: :: :: :: :: :: :: :: :: :: :: :: ::
:: Go to the TEMP directory to create the required temporary files here
PUSHD "%Temp%"
:: Remove previous versions of the temporary files
FOR %%A IN (~Dir1.md5 ~Dir1.tmp ~Dir2.md5 ~Dir2.tmp fciv.err) DO IF EXIST %%A DEL %%A
ECHO Scanning %Dir1% and subdirectories . . .
FCIV.EXE %Dir1% -md5 -r %Type% | FINDSTR /R /B /I /C:"[0-9a-f][0-9a-f][0-9a-f]* [a-z\\][:\\]" | SORT /+33 > ~Dir1.md5
ECHO Scanning %Dir2% and subdirectories . . .
FCIV.EXE %Dir2% -md5 -r %Type% | FINDSTR /R /B /I /C:"[0-9a-f][0-9a-f][0-9a-f]* [a-z\\][:\\]" | SORT /+33 > ~Dir2.md5
:: Abort if no files were found in either directory (i.e. if either checksums list is 0 bytes)
FOR %%A IN (~Dir1.tmp) DO SET Size1=%%~zA
FOR %%A IN (~Dir2.tmp) DO SET Size2=%%~zA
IF %Size1%0 NEQ 0 IF %Size2%0 NEQ 0 (
REM Do nothing if both files are larger than 0 bytes
) ELSE (
IF %Size1%0 EQU 0 ECHO No files found in %Dir1%
IF %Size2%0 EQU 0 ECHO No files found in %Dir2%
ENDLOCAL
EXIT /B 3
)
TYPE NUL > ~Dir1.tmp
TYPE NUL > ~Dir2.tmp
IF /I "%~3"=="/DEBUG" (
SET Count=0
ECHO Removing specified path from ~Dir1.md5
)
FOR /F "tokens=*" %%A IN (~Dir1.md5) DO (
IF /I "%~3"=="/DEBUG" SET /A Count += 1
SET Line=%%A
IF /I "%~3"=="/DEBUG" ECHO [!Count!]!Line!
REM The following line of code would be vulnerable to a code insertion attack
REM (http://www.thesecurityfactory.be/command-injection-windows.html)
REM but we checked for ampersands earlier
FOR %%B IN (%Dir1%) DO SET Line=!Line:%%~B\=!
IF /I "%~3"=="/DEBUG" ECHO [!Count!]!Line!
>> ~Dir1.tmp ECHO.!Line!
)
IF /I "%~3"=="/DEBUG" (
SET Count=0
ECHO Removing specified path from ~Dir2.md5
)
FOR /F "tokens=*" %%A IN (~Dir2.md5) DO (
IF /I "%~3"=="/DEBUG" SET /A Count += 1
SET Line=%%A
IF /I "%~3"=="/DEBUG" ECHO [!Count!]!Line!
REM The following line of code would be vulnerable to a code insertion attack
REM (http://www.thesecurityfactory.be/command-injection-windows.html)
REM but we checked for ampersands earlier
FOR %%B IN (%Dir2%) DO SET Line=!Line:%%~B\=!
IF /I "%~3"=="/DEBUG" ECHO [!Count!]!Line!
>> ~Dir2.tmp ECHO.!Line!
)
ECHO Comparing checksums . . .
SET Error=0
FC.EXE /C ~Dir1.tmp ~Dir2.tmp | MORE +1 || SET Error=2
:: Remove trash
IF /I NOT "%~3"=="/DEBUG" (
DEL ~Dir1.md5
DEL ~Dir1.tmp
DEL ~Dir2.md5
DEL ~Dir2.tmp
DEL fciv.err
)
POPD
:: Exit with error level 2 in case of mismatch
ENDLOCAL & EXIT /B %Error%
:Syntax
IF /I "%~3"=="/DEBUG" SET Dir1
IF /I "%~3"=="/DEBUG" SET Dir2
IF /I "%~3"=="/DEBUG" SET Type
ECHO.
ECHO DirComp.bat, Version 3.30 for Windows NT
ECHO Compare the contents of 2 directories
ECHO.
ECHO Usage: DIRCOMP "d:\path\*.ext" "e:\otherfolder" [/C]
ECHO or: DIRCOMP "d:\path\" "e:\otherfolder" [/C]
ECHO.
ECHO Where: /C Continues comparison even if total file size does not match
ECHO.
ECHO Notes: Note the trailing backslash if the first argument is a folder.
ECHO Compares number of files, file size, timestamp and contents of files.
ECHO Requires Microsoft's File Checksum Integrity Verifier utility (FCIV),
ECHO available at http://support.microsoft.com/kb/841290
ECHO If FCIV is not available, you will be prompted to download it.
ECHO Uses FC to compare FCIV's checksum listings; so if differences are
ECHO found, the lines immediately preceeding and following a line that
ECHO differs are displayed as well.
ECHO Ampersands are not allowed in the folder paths.
ECHO.
ECHO Written by Rob van der Woude
ECHO http://www.robvanderwoude.com
IF "%OS%"=="Windows_NT" EXIT /B 1
page last modified: 2024-04-16; loaded in 0.0116 seconds