Powered by GeSHi

Source code for dircomp.bat

(view source code of dircomp.bat as plain text)

  1. @ECHO OFF
  2. :: Check Windows version
  3. IF NOT "%OS%"=="Windows_NT" GOTO Syntax
  4.  
  5. :: Only /DEBUG is valid as optional third argument
  6. IF NOT "%~3"=="" IF /I NOT "%~3"=="/C" IF /I NOT "%~3"=="/DEBUG" GOTO Syntax
  7.  
  8. :: Two command line arguments are mandatory
  9. IF "%~1"=="" GOTO Syntax
  10. IF "%~2"=="" GOTO Syntax
  11.  
  12. :: If the first argument is not a folder, it should end with \*.ext"
  13. IF NOT "%~x1"=="" (
  14. 	ECHO "%~1"| FINDSTR /R /E /I /C:"\\\*\%~x1." >NUL || GOTO Syntax
  15. )
  16.  
  17. :: Initial check if (files and) folders exist
  18. IF NOT EXIST "%~1" GOTO Syntax
  19. IF NOT EXIST "%~2" GOTO Syntax
  20.  
  21. SETLOCAL ENABLEDELAYEDEXPANSION
  22.  
  23. :: Reset the variables we are going to use
  24. SET AllFiles1=
  25. SET AllFiles2=
  26. SET Dir1=
  27. SET Dir2=
  28. SET FileSpec1=
  29. SET FileSpec2=
  30. SET FileType=*.*
  31. SET NumFiles1=0
  32. SET NumFiles2=0
  33. SET TotalFiles1=
  34. SET TotalFiles2=
  35. SET TotalLine1=
  36. SET TotalLine2=
  37. SET TotalSize1=
  38. SET TotalSize2=
  39. SET Type=
  40.  
  41. :: Check if FCIV is available, and if not, prompt to open its download page
  42. :: Code corrected in version 3.10, as the earlier versions failed to detect
  43. :: the absence of FCIV.EXE (thanks Ron Guggisberg for finding this bug)
  44. ECHO Checking availability of FCIV utility . . .
  45. SET Answer=
  46. FCIV.EXE -h >NUL 2>&1
  47. IF ERRORLEVEL 1 (
  48. 	ECHO This batch file requires Microsoft's File Checksum Integrity Verifier utility
  49. 	ECHO ^(FCIV.EXE^), available at http://support.microsoft.com/kb/841290
  50. 	ECHO.
  51. 	SET Answer=N
  52. 	SET /P Answer=Do you want to open the download page now? [y/N] 
  53. 	IF /I NOT "!Answer!"=="Y" GOTO Syntax
  54. 	CLS
  55. 	ECHO.
  56. 	ECHO You are about to open Microsoft's FCIV download page.
  57. 	ECHO Download and install FCIV.EXE and restart this batch file.
  58. 	ECHO.
  59. 	PAUSE
  60. 	START http://support.microsoft.com/kb/841290
  61. 	ENDLOCAL
  62. 	GOTO:EOF
  63. )
  64.  
  65. IF NOT "%~nx1"=="" (
  66. 	SET FileType=*%~x1
  67. 	SET Type=-type *%~x1
  68. )
  69.  
  70. :: Quick and dirty way to check if directories exist and handle trailing backslashes in one go
  71. PUSHD "%~dp1"
  72. IF ERRORLEVEL 1 (
  73. 	ENDLOCAL
  74. 	GOTO Syntax
  75. ) ELSE (
  76. 	CD | FIND "&" >NUL
  77. 	IF ERRORLEVEL 1 (
  78. 		SET AllFiles1="!__CD__!*.*"
  79. 		SET Dir1="!CD!"
  80. 		SET FileSpec1="!__CD__!%FileType%"
  81. 		POPD
  82. 	) ELSE (
  83. 		POPD
  84. 		GOTO Syntax
  85. 	)
  86. )
  87. PUSHD "%~f2"
  88. IF ERRORLEVEL 1 (
  89. 	ENDLOCAL
  90. 	GOTO Syntax
  91. ) ELSE (
  92. 	CD | FIND "&" >NUL
  93. 	IF ERRORLEVEL 1 (
  94. 		SET AllFiles2="!__CD__!*.*"
  95. 		SET Dir2="!CD!"
  96. 		SET FileSpec2="!__CD__!%FileType%"
  97. 		POPD
  98. 	) ELSE (
  99. 		POPD
  100. 		GOTO Syntax
  101. 	)
  102. )
  103.  
  104. :: :: :: :: :: :: :: :: :: :: :: :: :: :: ::
  105. ::                                        ::
  106. :: Part I: just check the total file size ::
  107. ::                                        ::
  108. :: :: :: :: :: :: :: :: :: :: :: :: :: :: ::
  109.  
  110. ECHO Checking number of files and total file size for both directories . . .
  111.  
  112. :: Get number of matching files and total file size for first directory
  113. FOR /F %%A IN ('DIR "%~1" /S ^| FIND /C "("') DO SET /A TotalLine1 = %%A - 1
  114. FOR /F "tokens=2,4" %%A IN ('DIR "%~1" /-C /S ^| FIND "(" ^| FIND /N "(" ^| FIND "[%TotalLine1%]"') DO (
  115. 	SET TotalFiles1=%%A
  116. 	SET TotalSize1=%%B
  117. )
  118.  
  119. :: Get number of matching files and total file size for second directory
  120. FOR /F %%A IN ('DIR "%FileSpec2%" /S ^| FIND /C "("') DO SET /A TotalLine2 = %%A - 1
  121. FOR /F "tokens=2,4" %%A IN ('DIR %FileSpec2% /-C /S ^| FIND "(" ^| FIND /N "(" ^| FIND "[%TotalLine2%]"') DO (
  122. 	SET TotalFiles2=%%A
  123. 	SET TotalSize2=%%B
  124. )
  125.  
  126. :: Abort if the NUMBER of matching files does not match
  127. IF NOT %TotalFiles1% EQU %TotalFiles2% (
  128. 	ECHO Number of files is different:
  129. 	ECHO %TotalFiles1% files in %Dir1%
  130. 	ECHO %TotalFiles2% files in %Dir2%
  131. 	ECHO.
  132. 	ECHO Aborting comparison . . .
  133. 	ECHO.
  134. 	ENDLOCAL
  135. 	EXIT /B 2
  136. )
  137.  
  138. :: Warn if the TOTAL SIZE of the files does not match
  139. IF NOT %TotalSize1% EQU %TotalSize2% (
  140. 	ECHO Total file size is different:
  141. 	ECHO %TotalSize1% bytes in %Dir1%
  142. 	ECHO %TotalSize2% bytes in %Dir2%
  143. 	ECHO.
  144. 	IF /I "%~3"=="/C" (
  145. 		ECHO Continuing comparison . . .
  146. 		ECHO.
  147. 	) ELSE (
  148. 		ECHO Aborting comparison . . .
  149. 		ECHO.
  150. 		ENDLOCAL
  151. 		EXIT /B 2
  152. 	)
  153. )
  154.  
  155. :: :: :: :: :: :: :: :: :: :: :: :: ::
  156. ::                                  ::
  157. :: Part II: compare file timestamps ::
  158. ::                                  ::
  159. :: :: :: :: :: :: :: :: :: :: :: :: ::
  160.  
  161. ECHO Comparing files' timestamps for both directories . . .
  162.  
  163. :: XCOPY /D /Y /L just checks what is newer without actually copying anything
  164. FOR /F %%A IN ('XCOPY %FileSpec1% %AllFiles2% /S /D /H /R /Y /L 2^>NUL') DO SET NumFiles1=%%A
  165. FOR /F %%A IN ('XCOPY %FileSpec2% %AllFiles1% /S /D /H /R /Y /L 2^>NUL') DO SET NumFiles2=%%A
  166. IF %NumFiles1% EQU 0 IF %NumFiles2% EQU 0 (
  167. 	REM Do nothing if all timestamps match
  168. ) ELSE (
  169. 	IF %NumFiles2% GTR 0 ECHO %NumFiles2% files in %Dir1% are older
  170. 	IF %NumFiles1% GTR 0 ECHO %NumFiles1% files in %Dir2% are older
  171. )
  172.  
  173. :: :: :: :: :: :: :: :: :: :: :: :: :: :: ::
  174. ::                                        ::
  175. :: Part III: compare checksums per file   ::
  176. ::                                        ::
  177. :: :: :: :: :: :: :: :: :: :: :: :: :: :: ::
  178.  
  179. :: Go to the TEMP directory to create the required temporary files here
  180. PUSHD "%Temp%"
  181.  
  182. :: Remove previous versions of the temporary files
  183. FOR %%A IN (~Dir1.md5 ~Dir1.tmp ~Dir2.md5 ~Dir2.tmp fciv.err) DO IF EXIST %%A DEL %%A
  184.  
  185. ECHO Scanning %Dir1% and subdirectories . . .
  186. 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
  187.  
  188. ECHO Scanning %Dir2% and subdirectories . . .
  189. 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
  190.  
  191. :: Abort if no files were found in either directory (i.e. if either checksums list is 0 bytes)
  192. FOR %%A IN (~Dir1.tmp) DO SET Size1=%%~zA
  193. FOR %%A IN (~Dir2.tmp) DO SET Size2=%%~zA
  194. IF %Size1%0 NEQ 0 IF %Size2%0 NEQ 0 (
  195. 	REM Do nothing if both files are larger than 0 bytes
  196. ) ELSE (
  197. 	IF %Size1%0 EQU 0 ECHO No files found in %Dir1%
  198. 	IF %Size2%0 EQU 0 ECHO No files found in %Dir2%
  199. 	ENDLOCAL
  200. 	EXIT /B 3
  201. )
  202.  
  203. TYPE NUL > ~Dir1.tmp
  204. TYPE NUL > ~Dir2.tmp
  205. IF /I "%~3"=="/DEBUG" (
  206. 	SET Count=0
  207. 	ECHO Removing specified path from ~Dir1.md5
  208. )
  209. FOR /F "tokens=*" %%A IN (~Dir1.md5) DO (
  210. 	IF /I "%~3"=="/DEBUG" SET /A Count += 1
  211. 	SET Line=%%A
  212. 	IF /I "%~3"=="/DEBUG" ECHO [!Count!]!Line!
  213. 	REM The following line of code would be vulnerable to a code insertion attack
  214. 	REM (http://www.thesecurityfactory.be/command-injection-windows.html)
  215. 	REM but we checked for ampersands earlier
  216. 	FOR %%B IN (%Dir1%) DO SET Line=!Line:%%~B\=!
  217. 	IF /I "%~3"=="/DEBUG" ECHO [!Count!]!Line!
  218. 	>> ~Dir1.tmp ECHO.!Line!
  219. )
  220. IF /I "%~3"=="/DEBUG" (
  221. 	SET Count=0
  222. 	ECHO Removing specified path from ~Dir2.md5
  223. )
  224. FOR /F "tokens=*" %%A IN (~Dir2.md5) DO (
  225. 	IF /I "%~3"=="/DEBUG" SET /A Count += 1
  226. 	SET Line=%%A
  227. 	IF /I "%~3"=="/DEBUG" ECHO [!Count!]!Line!
  228. 	REM The following line of code would be vulnerable to a code insertion attack
  229. 	REM (http://www.thesecurityfactory.be/command-injection-windows.html)
  230. 	REM but we checked for ampersands earlier
  231. 	FOR %%B IN (%Dir2%) DO SET Line=!Line:%%~B\=!
  232. 	IF /I "%~3"=="/DEBUG" ECHO [!Count!]!Line!
  233. 	>> ~Dir2.tmp ECHO.!Line!
  234. )
  235.  
  236. ECHO Comparing checksums . . .
  237. SET Error=0
  238. FC.EXE /C ~Dir1.tmp ~Dir2.tmp | MORE +1 || SET Error=2
  239.  
  240. :: Remove trash
  241. IF /I NOT "%~3"=="/DEBUG" (
  242. 	DEL ~Dir1.md5
  243. 	DEL ~Dir1.tmp
  244. 	DEL ~Dir2.md5
  245. 	DEL ~Dir2.tmp
  246. 	DEL fciv.err
  247. )
  248.  
  249. POPD
  250.  
  251. :: Exit with error level 2 in case of mismatch
  252. ENDLOCAL & EXIT /B %Error%
  253.  
  254.  
  255. :Syntax
  256. IF /I "%~3"=="/DEBUG" SET Dir1
  257. IF /I "%~3"=="/DEBUG" SET Dir2
  258. IF /I "%~3"=="/DEBUG" SET Type
  259. ECHO.
  260. ECHO DirComp.bat,  Version 3.30 for Windows NT
  261. ECHO Compare the contents of 2 directories
  262. ECHO.
  263. ECHO Usage:  DIRCOMP  "d:\path\*.ext"  "e:\otherfolder"  [/C]
  264. ECHO    or:  DIRCOMP  "d:\path\"       "e:\otherfolder"  [/C]
  265. ECHO.
  266. ECHO Where:  /C       Continues comparison even if total file size does not match
  267. ECHO.
  268. ECHO Notes:  Note the trailing backslash if the first argument is a folder.
  269. ECHO         Compares number of files,  file size, timestamp and contents of files.
  270. ECHO         Requires Microsoft's File Checksum Integrity Verifier utility (FCIV),
  271. ECHO         available at http://support.microsoft.com/kb/841290
  272. ECHO         If FCIV is not available, you will be prompted to download it.
  273. ECHO         Uses FC to compare FCIV's checksum listings; so if differences are
  274. ECHO         found, the lines immediately preceeding and following a line that
  275. ECHO         differs are displayed as well.
  276. ECHO         Ampersands are not allowed in the folder paths.
  277. ECHO.
  278. ECHO Written by Rob van der Woude
  279. ECHO http://www.robvanderwoude.com
  280.  
  281. IF "%OS%"=="Windows_NT" EXIT /B 1
  282.