Search code examples
for-loopbatch-filefilenameschecksumcertutil

Output each checksum with its corresponding filename to seperate lines in a text file


I'm trying to output a checksum for six hundred tif files in a directory. I want each line to show the checksum followed by its respective file name.

For example:

b1039a6f0c4295916a82833f507f5e78 vol1_0001.tif
dd3fb454e8d4912934f7626baf105e36 vol1_0002.tif
etc.

Here is what I have tried:

for %%F in (vol1*.*) do certutil -hashfile "%%F" md5 | find /V "hash" >>temp.txt
for %%a in (vol1*.*) do set filename=%%~nxa
for /f "tokens=* delims=" %%i in (temp.txt) do set hash=%%i
@echo %hash% %filename% >>CheckSum.md5

The first part works fine, and I get a .txt file of all the checksums I need. But the second part is not working.

All I get is the checksum, and file name pair, for the last file in the directory, repeated a bunch of times.

I have also tried this way on the recommendation of a colleague, but this didn't work either:

@echo off
Set "Folder=C:\Users\Me\desktop\MyFolder"
Set "OutPutFile=%~dp0HashList.md5"
Type nul>"%OutPutFile%"    

SetLocal EnableDelayedExpansion
@for /f "delims=" %%a in ('Dir /S /B /A-D "%Folder%"') do (
@for /f "skip=1 delims=" %%H in ('CertUtil -hashfile "%%~a" md5 ^| find /V      "hash"') do set "Hash=%%H"
    echo %%a, !Hash: =! 
    echo %%a, !Hash: =! >>"%OutPutFile%"
)

I got a list of the file names, but each had the exact same checksum (for the last file in the directory).


Solution

  • This code solves your problem in the most efficient way:

    @echo off
    setlocal
    set "Folder=C:\Users\Me\desktop\MyFolder"
    set "OutPutFile=%~dp0HashList.md5"
    
    (
       for %%F in ("%Folder%\vol1*.*") do (
          set "hash="
          for /F "skip=1" %%a in ('certutil -hashfile "%%F" md5') do (
             if not defined hash (
                echo %%a %%F
                set "hash=1"
             )
          )
       )
    ) > "%OutPutFile%"
    

    This approach include these efficiency features:

    • It does not open/seek EOF/write/close the result file to output every checksum line, but keeps it open for all output lines
    • It does not use an external .exe program (like find.exe) to locate the hash line of every file, but take it directly from the second output line

    If the number of files to process is large, like six hundred files, the difference in time from this method to other one that uses find and append >> redirection will be very noticeable...