New function - :hexDump

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

New function - :hexDump

#1 Post by dbenham » 27 Apr 2011 23:57

A much faster version of HEXDUMP.BAT based on CERTUTIL is available at viewtopic.php?f=3&t=8816

Jeb posted a clever technique for reading binary files as an addendum to the ROT13 encryption thread.

I've expanded the concept into a flexible hexDump routine with a good number of options. I've done some testing, but with all the options I wouldn't be surprised if there are some bugs lurking somewhere. In theory it should be able to handle reading up to 2 gigabytes, but I don't recommend it! As long as the /S option startOffset is in the tens of thousands then performance isn't too bad. But I tried looking at 200 bytes with startOffset=200000 and the wait was painful.

hexDump.bat

Code: Select all

@echo off
:hexDump [/option]... file  -- dump a file in hex format
::
::  Displays the content of a binary file using a pair of hexadecimal digits
::  for each byte. By default the ouput displays 16 bytes per line, with the
::  the bytes (hexadecimal pairs) delimited by a space.
::
::  The format of the dump can be modified by the following case insensitive
::  options:
::
::    /BblockSize   The blockSize after the /B specifies the number of bytes
::                  to print in each block. Bytes within a block are not
::                  delimited. If the blockSize is <= 0 then /C, /A and /O
::                  options are ignored and the bytes are output in a
::                  continuous stream without any delimiters or linebreaks.
::                  The default blockSize is 1.
::
::    /CblockCount  The blockCount after the /C specifies the number of blocks
::                  to include on each line of output. Blocks are delimited
::                  by a space.
::                  The default blockCount is 16.
::
::    /SstartOffset The startOffset after the /S specifies the number of bytes
::                  to skip before displaying bytes.
::                  The default startOffset is 0.
::
::    /Nlengh       The length after the /N specifies the total number of
::                  bytes to display after the startOffset. The default is to
::                  display up until the end of the file.
::
::    /A            Append the ASCII representation of the bytes to the end
::                  of each line. Non-printable and extended ASCII characters
::                  are displayed as periods.
::
::    /O            Prefix each line with the starting offset of the line in
::                  hexadecimal notation.
::
::  Each option must be entered as a separate argument.
::
  setlocal enableDelayedExpansion
  set /a blockSize=1, blockCount=16, startOffset=0
  set ascii=
  set offset=
  set len=
  set opts=
  for %%a in (%*) do (
    if not defined opts (
      set "arg=%%~a"
      if "!arg:~0,1!"=="/" (
        shift /1
        set "opt=!arg:~1,1!"
        if /i "!opt!"=="B" set /a blockSize=!arg:~2!
        if /i "!opt!"=="C" set /a blockCount=!arg:~2!
        if /i "!opt!"=="S" set /a startOffset=!arg:~2!
        if /i "!opt!"=="N" set /a len=!arg:~2!
        if /i "!opt!"=="A" set "ascii=  "
        if /i "!opt!"=="O" set offset=TRUE
      ) else set opts=TRUE
    )
  )
  if not exist %1 (
    echo ERROR: File not found >&2
    exit /b 1
  )
  set fileSize=%~z1
  if defined len (
    set /a "endOffset = startOffset + len"
    if !endOffset! gtr %fileSise% set endOffset=%fileSize%
  ) else set endOffset=%fileSize%
  if defined offset set offset=%startOffset%
  set "blockDelim= "
  if %blockSize% lss 1 (
    set /a "blockSize=0, blockCount=2000"
    set "ascii="
    set "offset="
    set "blockDelim="
  )
  set dummy="!temp!\hexDumpDummy%random%.txt"
  <nul >%dummy% set /p ".=A"
  set dummySize=1
  for /l %%n in (1,1,32) do (if !dummySize! lss %endOffset% set /a "dummySize*=2" & type !dummy! >>!dummy!)
  set /a "pos=0, cnt=0, skipStart=startOffset+1, lnBytes=blockSize*blockCount"
  set "off="
  set "hex="
  set "txt=%ascii%"
  set map= ^^^!^"#$%%^&'^(^)*+,-./0123456789:;^<=^>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^^^^_`abcdefghijklmnopqrstuvwxyz{^|}~
  set hexMap=0123456789ABCDEF
  for /f "eol=F usebackq tokens=1,2 skip=1 delims=:[] " %%A in (`fc /b "%~dpf1" %dummy%`) do (
    set /a skipEnd=0x%%A && (
      if !skipEnd! geq %startOffset% if !skipStart! leq %endOffset% (
        for /l %%n in (!skipStart!,1,!skipEnd!) do call :hexDump.addChar 41
        call :hexDump.addChar %%B
        set /a skipStart=skipEnd+2
      )
    )
  )
  for /l %%n in (%skipStart%,1,%endOffset%) do call :hexDump.addChar 41
  if %blockSize%==0 if defined hex call :hexDump.writeLn
  for /l %%n in (1,1,%lnBytes%) do if defined hex call :hexDump.addChar "  "
  del %dummy%
  exit /b
  :hexDump.addChar  hexPair
    set "hex=!hex!%~1"
    if defined ascii (
      2>nul set /a "d=0x%1-32" && (
        if !d! lss 0 set d=14
        if !d! gtr 94 set d=14
        for %%d in (!d!) do set txt=!txt!!map:~%%d,1!
      )
    )
    if %blockSize% gtr 0 set /a pos+=1
    if !pos!==%blockSize% set /a "pos=0, cnt+=1"
    if not !cnt!==!blockCount! (
		  if !pos!==0 set "hex=!hex!%blockDelim%"
			exit /b
		)
    set cnt=0
  :hexDump.writeLn
    if defined offset (
      set off=
      set dec=!offset!
      for /l %%n in (1,1,8) do (
        set /a "d=dec&15,dec>>=4"
        for %%d in (!d!) do set "off=!hexMap:~%%d,1!!off!"
      )
      set "off=!off!: "
      set /a offset+=lnBytes
    )
    set "ln=!off!!hex!!txt!"
    if %blockSize%==0 (<nul set /p ".=!ln!") else echo !ln!
    set hex=
    set "txt=%ascii%"
exit /b
Here is output using a few of the options. I dumped the 1st 200 bytes of the hexDump.bat file.

Code: Select all

>hexdump /a /o /n200 hexdump.bat
00000000: 40 65 63 68 6F 20 6F 66 66 0D 0A 3A 68 65 78 44  @echo off..:hexD
00000010: 75 6D 70 20 5B 2F 6F 70 74 69 6F 6E 5D 2E 2E 2E  ump [/option]...
00000020: 20 66 69 6C 65 20 20 2D 2D 20 64 75 6D 70 20 61   file  -- dump a
00000030: 20 66 69 6C 65 20 69 6E 20 68 65 78 20 66 6F 72   file in hex for
00000040: 6D 61 74 0D 0A 3A 3A 0D 0A 3A 3A 20 20 44 69 73  mat..::..::  Dis
00000050: 70 6C 61 79 73 20 74 68 65 20 63 6F 6E 74 65 6E  plays the conten
00000060: 74 20 6F 66 20 61 20 62 69 6E 61 72 79 20 66 69  t of a binary fi
00000070: 6C 65 20 75 73 69 6E 67 20 61 20 70 61 69 72 20  le using a pair
00000080: 6F 66 20 68 65 78 61 64 65 63 69 6D 61 6C 20 64  of hexadecimal d
00000090: 69 67 69 74 73 0D 0A 3A 3A 20 20 66 6F 72 20 65  igits..::  for e
000000A0: 61 63 68 20 62 79 74 65 2E 20 42 79 20 64 65 66  ach byte. By def
000000B0: 61 75 6C 74 20 74 68 65 20 6F 75 70 75 74 20 64  ault the ouput d
000000C0: 69 73 70 6C 61 79 73 20                          isplays
Dave Benham
Last edited by dbenham on 29 Jan 2014 19:53, edited 1 time in total.

nitt
Posts: 218
Joined: 22 Apr 2011 02:43

Re: New function - :hexDump

#2 Post by nitt » 28 Apr 2011 18:21

I tried this with an executable and got a crap-ton of hex. I then converted all the hex to characters with VBScript and got "MZ".

I also hexdumped a .vbs file, then used the converter to read the hex and I got something close to the original, but not the same:

Original:

Code: Select all

set fc = createobject("scripting.filesystemobject")
string1 = fc.opentextfile("test.txt").readall

arry1 = split(string1," ")
final = ""
for each a in arry1
on error resume next
final = final & chr(CLng("&h" & a))
next

msgbox(final)




After converting:

Code: Select all

set fc = createject("scriptinfilesystemobje")
string1 = .opentextfile(est.exe").readl

arry1 = sit(string1," "
final = ""
f each a in arr
on error rese next
final final & chr(CL("&h" & a))
nt

msgbox(fil)

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: New function - :hexDump

#3 Post by dbenham » 28 Apr 2011 21:20

Thanks for testing nitt, but I am unable to reproduce your results.

I copied your test source code into a file named original.txt and then ran the following test.bat

Code: Select all

setlocal enableDelayedExpansion
call hexdump /b0 original.txt >original.hex
echo on
for /f %%h in ('type original.hex') do set hex=%%h
call charlib hex2str hex str
echo on
:: The following "echos" the value of str without introducing a new line
:: with the output redirected to copy.txt
<nul >copy.txt set /p ".=!str!"
type copy.txt
fc original.txt copy.txt

The charlib utility I am using to convert from hex to a string can be found here dbenham files and is the result of collaboration in this thread character conversion functions - :asc, :chr, :str2hex, :hex2str

Here are my results demonstrating successful conversion to and from hex: The only editing I did was to introduce line continuation in the set hex statement results.

Code: Select all

>test

>setlocal enableDelayedExpansion

>call hexdump /b0 original.txt  1>original.hex

>for /F %h in ('type original.hex') do set hex=%h

>set hex=736574206663203D206372656174656F626A6563742822736372697^
074696E672E66696C6573797374656D6F626A65637422290D0A737472696E67^
31203D2066632E6F70656E7465787466696C652822746573742E74787422292E^
72656164616C6C0D0A0D0A6172727931203D2073706C697428737472696E673^
12C222022290D0A66696E616C203D2022220D0A666F72206561636820612069^
6E2061727279310D0A6F6E206572726F7220726573756D65206E6578740D0A6^
6696E616C203D2066696E616C20262063687228434C6E672822266822202620^
6129290D0A6E6578740D0A0D0A6D7367626F782866696E616C290D0A

>call charlib hex2str hex str

>set /p ".=!str!" 0<nul 1>copy.txt

>type copy.txt
set fc = createobject("scripting.filesystemobject")
string1 = fc.opentextfile("test.txt").readall

arry1 = split(string1," ")
final = ""
for each a in arry1
on error resume next
final = final & chr(CLng("&h" & a))
next

msgbox(final)

>fc original.txt copy.txt
Comparing files original.txt and COPY.TXT
FC: no differences encountered



Hopefully the problem is with your conversion code and not a Windows version issue (or God forbid a bug in my code :roll: ) One other possibility is I am running a more recent version of hexDump with a few more options, but no bug fixes that I am aware of.

If you still think you have found a bug in hexDump.bat, please post a short test file, the hexDump command line you used, and the hexDump output. Posting only your conversion results leaves open the possibility that the bug is on your end.

Here is the "final" version of hexDump, barring bug fixes. It now supports user defined delimiters within and between blocks, as well as user definable default formatting via an environment variable:

Code: Select all


@echo off
:hexDump [/option]... file  -- dump a file in hex format
::
::  Displays the content of a binary file using a pair of hexadecimal digits
::  for each byte. By default the ouput displays 16 bytes per line, with the
::  bytes (hexadecimal pairs) delimited by a space.
::
::  The format of the dump can be modified by the following case insensitive
::  options:
::
::    /BblockSize   The blockSize after the /B specifies the number of bytes
::                  to print in each block. If the blockSize is <= 0 then /C,
::                  /D, /E, /A and /O options are ignored and the bytes are
::                  output in a continuous stream without any delimiters or
::                  linebreaks.
::                  The default blockSize is 1.
::
::    /CblockCount  The blockCount after the /C specifies the number of blocks
::                  to include on each line of output.
::                  The default blockCount is 16.
::
::    /DbyteDelim   The byteDelim after the /D specifies the delimiter string
::                  to use between bytes within a block.
::                  The default byteDelim is undefined (no delimiter)
::
::    /EblockDelim  The blockDelim after the /E specifies the delimiter string
::                  to use between blocks within a line.
::                  The default blockDelim is "/E " (a single space)
::
::    /SstartOffset The startOffset after the /S specifies the number of bytes
::                  to skip before displaying bytes.
::                  The default startOffset is 0.
::
::    /Nlength      The length after the /N specifies the total number of
::                  bytes to display after the startOffset. The default is to
::                  display up until the end of the file.
::
::    /A            Append the ASCII representation of the bytes to the end
::                  of each line. Non-printable and extended ASCII characters
::                  are displayed as periods.
::
::    /O            Prefix each line with the starting offset of the line in
::                  hexadecimal notation.
::
::  Each option must be entered as a separate argument. Numeric components to
::  options may be specified using any numeric expression supported by SET /A.
::  The option defaults may be modified by presetting a hexDumpDefaults
::  variable.
::
  setlocal enableDelayedExpansion
  set /a blockSize=1, blockCount=16, startOffset=0
  set ascii=
  set offset=
  set len=
  set opts=
  set byteDelim=
  set "blockDelim= "
  set endDefault=
  for %%a in (!hexDumpDefaults! // %*) do (
    if not defined opts (
      set "arg=%%~a"
      if "!arg:~0,1!"=="/" (
        if defined endDefault shift /1
        set "opt=!arg:~1,1!"
        if /i "!opt!"=="B" set /a blockSize=!arg:~2!
        if /i "!opt!"=="C" set /a blockCount=!arg:~2!
        if /i "!opt!"=="D" set "byteDelim=!arg:~2!"
        if /i "!opt!"=="E" set "blockDelim=!arg:~2!"
        if /i "!opt!"=="S" set /a startOffset=!arg:~2!
        if /i "!opt!"=="N" set /a len=!arg:~2!
        if /i "!opt!"=="A" set "ascii=  "
        if /i "!opt!"=="O" set offset=TRUE
        if /i "!opt!"=="/" set endDefault=true
      ) else set opts=TRUE
    )
  )
  if not exist %1 (
    echo ERROR: File not found >&2
    exit /b 1
  )
  set fileSize=%~z1
  if defined len (
    set /a "endOffset = startOffset + len"
    if !endOffset! gtr %fileSise% set endOffset=%fileSize%
  ) else set endOffset=%fileSize%
  if defined offset set offset=%startOffset%
  if %blockSize% lss 1 (
    set /a "blockSize=0, blockCount=2000"
    set "ascii="
    set "offset="
    set "byteDelim="
    set "blockDelim="
  )
  set dummy="!temp!\hexDumpDummy%random%.txt"
  <nul >%dummy% set /p ".=A"
  set dummySize=1
  for /l %%n in (1,1,32) do (if !dummySize! lss %endOffset% set /a "dummySize*=2" & type !dummy! >>!dummy!)
  set /a "pos=0, cnt=0, skipStart=startOffset+1, lnBytes=blockSize*blockCount"
  set "off="
  set "hex="
  set "txt=%ascii%"
  set map= ^^^!^"#$%%^&'^(^)*+,-./0123456789:;^<=^>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^^^^_`abcdefghijklmnopqrstuvwxyz{^|}~
  set hexMap=0123456789ABCDEF
  for /f "eol=F usebackq tokens=1,2 skip=1 delims=:[] " %%A in (`fc /b "%~dpf1" %dummy%`) do (
    set /a skipEnd=0x%%A && (
      if !skipEnd! geq %startOffset% if !skipStart! leq %endOffset% (
        for /l %%n in (!skipStart!,1,!skipEnd!) do call :hexDump.addChar 41
        call :hexDump.addChar %%B
        set /a skipStart=skipEnd+2
      )
    )
  )
  for /l %%n in (%skipStart%,1,%endOffset%) do call :hexDump.addChar 41
  if %blockSize%==0 if defined hex call :hexDump.writeLn
  for /l %%n in (1,1,%lnBytes%) do if defined hex call :hexDump.addChar "  "
  del %dummy%
  exit /b
  :hexDump.addChar  hexPair
    if defined ascii (
      2>nul set /a "d=0x%1-32" && (
        if !d! lss 0 set d=14
        if !d! gtr 94 set d=14
        for %%d in (!d!) do set txt=!txt!!map:~%%d,1!
      )
    )
    if %blockSize% gtr 0 set /a pos+=1
    if !pos!==%blockSize% set /a "pos=0, cnt+=1"
    if not !cnt!==!blockCount! (
      if !pos!==0 (set "hex=!hex!%~1!blockDelim!") else set "hex=!hex!%~1!byteDelim!"
      exit /b
    )
    set "hex=!hex!%~1"
    set cnt=0
  :hexDump.writeLn
    if defined offset (
      set off=
      set dec=!offset!
      for /l %%n in (1,1,8) do (
        set /a "d=dec&15,dec>>=4"
        for %%d in (!d!) do set "off=!hexMap:~%%d,1!!off!"
      )
      set "off=!off!: "
      set /a offset+=lnBytes
    )
    set "ln=!off!!hex!!txt!"
    if %blockSize%==0 (<nul set /p ".=!ln!") else echo !ln!
    set hex=
    set "txt=%ascii%"
exit /b


Finally here are results demonstrating the new features:

Code: Select all


>set hexDumpDefaults=/o /a /b8 /c2 "/d " "/e - "

>hexdump /s150 /n200 hexdump.bat
00000096: 0A 3A 3A 20 20 66 6F 72 - 20 65 61 63 68 20 62 79  .::  for each by
000000A6: 74 65 2E 20 42 79 20 64 - 65 66 61 75 6C 74 20 74  te. By default t
000000B6: 68 65 20 6F 75 70 75 74 - 20 64 69 73 70 6C 61 79  he ouput display
000000C6: 73 20 31 36 20 62 79 74 - 65 73 20 70 65 72 20 6C  s 16 bytes per l
000000D6: 69 6E 65 2C 20 77 69 74 - 68 20 74 68 65 0D 0A 3A  ine, with the..:
000000E6: 3A 20 20 62 79 74 65 73 - 20 28 68 65 78 61 64 65  :  bytes (hexade
000000F6: 63 69 6D 61 6C 20 70 61 - 69 72 73 29 20 64 65 6C  cimal pairs) del
00000106: 69 6D 69 74 65 64 20 62 - 79 20 61 20 73 70 61 63  imited by a spac
00000116: 65 2E 0D 0A 3A 3A 0D 0A - 3A 3A 20 20 54 68 65 20  e...::..::  The
00000126: 66 6F 72 6D 61 74 20 6F - 66 20 74 68 65 20 64 75  format of the du
00000136: 6D 70 20 63 61 6E 20 62 - 65 20 6D 6F 64 69 66 69  mp can be modifi
00000146: 65 64 20 62 79 20 74 68 - 65 20 66 6F 6C 6C 6F 77  ed by the follow
00000156: 69 6E 67 20 63 61 73 65 -                          ing case


Dave Benham

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: New function - :hexDump

#4 Post by dbenham » 21 May 2011 17:14

Up until now, all of my hexDump posts have relied on a "local" hexDump.addChar function that must be called for each character. This is a tremendous overhead. I remember wanting to embed the function code directly in the various loops, but the function was called 4 times, so I opted for improved readability and maintenance over performance.

But since there is now a mechanism for Batch "macros" with arguments, I can have my cake and eat it to! Here is a much faster version of hexDump that uses a macro to replace the :hexDump.addChar function. I've also added an /h option that provides help on the usage of hexDump. Running the batch file without any options will also display the help.

Code: Select all

@echo off
:hexDump [/option]... file        -- dump a file in hex format
::
::  Displays the content of a binary file using a pair of hexadecimal digits
::  for each byte. By default the ouput displays 16 bytes per line, with the
::  bytes (hexadecimal pairs) delimited by a space.
::
::  The format of the dump can be modified by the following case insensitive
::  options:
::
::    /BblockSize   The blockSize after the /B specifies the number of bytes
::                  to print in each block. If the blockSize is <= 0 then /C,
::                  /D, /E, /A and /O options are ignored and the bytes are
::                  output in a continuous stream without any delimiters or
::                  linebreaks.
::                  The default blockSize is 1.
::
::    /CblockCount  The blockCount after the /C specifies the number of blocks
::                  to include on each line of output.
::                  The default blockCount is 16.
::
::    /DbyteDelim   The byteDelim after the /D specifies the delimiter string
::                  to use between bytes within a block.
::                  The default byteDelim is undefined (no delimiter)
::
::    /EblockDelim  The blockDelim after the /E specifies the delimiter string
::                  to use between blocks within a line.
::                  The default blockDelim is "/E " (a single space)
::
::    /SstartOffset The startOffset after the /S specifies the number of bytes
::                  to skip before displaying bytes.
::                  The default startOffset is 0.
::
::    /Nlength      The length after the /N specifies the total number of
::                  bytes to display after the startOffset. The default is to
::                  display up until the end of the file.
::
::    /A            Append the ASCII representation of the bytes to the end
::                  of each line. Non-printable and extended ASCII characters
::                  are displayed as periods.
::
::    /O            Prefix each line with the starting offset of the line in
::                  hexadecimal notation.
::
::    /H            Display hexDump help
::
::  Each option must be entered as a separate argument. Numeric components to
::  options may be specified using any numeric expression supported by SET /A.
::  The option defaults may be modified by presetting a hexDumpDefaults
::  variable.
::
  setlocal enableDelayedExpansion
  set /a blockSize=1, blockCount=16, startOffset=0
  set ascii=
  set offset=
  set len=
  set opts=
  set byteDelim=
  set "blockDelim= "
  set endDefault=
  for %%a in (!hexDumpDefaults! // %*) do (
    if not defined opts (
      set "arg=%%~a"
      if "!arg:~0,1!"=="/" (
        if defined endDefault shift /1
        set "opt=!arg:~1,1!"
        if /i "!opt!"=="B" set /a blockSize=!arg:~2!
        if /i "!opt!"=="C" set /a blockCount=!arg:~2!
        if /i "!opt!"=="D" set "byteDelim=!arg:~2!"
        if /i "!opt!"=="E" set "blockDelim=!arg:~2!"
        if /i "!opt!"=="S" set /a startOffset=!arg:~2!
        if /i "!opt!"=="N" set /a len=!arg:~2!
        if /i "!opt!"=="A" set "ascii=  "
        if /i "!opt!"=="O" set offset=TRUE
        if /i "!opt!"=="H" set "opts=TRUE" & goto :hexDump.help
        if /i "!opt!"=="/" set endDefault=true
      ) else set opts=TRUE
    )
  )
  if "%~1"=="" goto :hexDump.help
  if not exist %1 (
    echo ERROR: File not found >&2
    exit /b 1
  )
  set fileSize=%~z1
  if defined len (
    set /a "endOffset = startOffset + len"
    if !endOffset! gtr %fileSize% set endOffset=%fileSize%
  ) else set endOffset=%fileSize%
  if defined offset set offset=%startOffset%
  if %blockSize% lss 1 (
    set /a "blockSize=0, blockCount=2000"
    set "ascii="
    set "offset="
    set "byteDelim="
    set "blockDelim="
  )
  set dummy="!temp!\hexDumpDummy%random%.txt"
  <nul >%dummy% set /p ".=A"
  set dummySize=1
  for /l %%n in (1,1,32) do (if !dummySize! lss %endOffset% set /a "dummySize*=2" & type !dummy! >>!dummy!)
  set /a "pos=0, cnt=0, skipStart=startOffset+1, lnBytes=blockSize*blockCount"
  set "off="
  set "hex="
  set "txt=%ascii%"
  set map= ^^^!^"#$%%^&'^(^)*+,-./0123456789:;^<=^>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^^^^_`abcdefghijklmnopqrstuvwxyz{^|}~
  set hexMap=0123456789ABCDEF
  ::DEFINE INTERNAL MACRO USED SOLELY BY THIS FUNCTION
  setlocal disableDelayedExpansion

  set LF=^


  ::Above 2 blank lines are required - do not remove

  set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"

  set callMacro=for /f %%a in

  set addChar= do (%\n%
    set "byte=%%~a"%\n%
    if "!byte!"=="2space" set "byte=  "%\n%
    if defined ascii if "!byte!" neq "  " (%\n%
      set /a "d=0x!byte!-32"%\n%
      if !d! lss 0 set d=14%\n%
      if !d! gtr 94 set d=14%\n%
      for %%d in (!d!) do set txt=!txt!!map:~%%d,1!%\n%
    )%\n%
    if %blockSize% gtr 0 set /a pos+=1%\n%
    if !pos!==%blockSize% set /a "pos=0, cnt+=1"%\n%
    if not !cnt!==!blockCount! (%\n%
      if !pos!==0 (set "hex=!hex!!byte!!blockDelim!") else set "hex=!hex!!byte!!byteDelim!"%\n%
    ) else (%\n%
      set "hex=!hex!!byte!"%\n%
      set cnt=0%\n%
      if defined offset (%\n%
        set off=%\n%
        set dec=!offset!%\n%
        for /l %%n in (1,1,8) do (%\n%
          set /a "d=dec&15,dec>>=4"%\n%
          for %%d in (!d!) do set "off=!hexMap:~%%d,1!!off!"%\n%
        )%\n%
        set "off=!off!: "%\n%
        set /a offset+=lnBytes%\n%
      )%\n%
      set "ln=!off!!hex!!txt!"%\n%
      if %blockSize%==0 (^<nul set /p ".=!ln!") else echo !ln!%\n%
      set hex=%\n%
      set "txt=%ascii%"%\n%
    )%\n%
  )

   ::END OF MACRO DEFS
  setlocal enableDelayedExpansion
  for /f "eol=F usebackq tokens=1,2 skip=1 delims=:[] " %%A in (`fc /b "%~dpf1" %dummy%`) do (
    set /a skipEnd=0x%%A && (
      if !skipEnd! geq %startOffset% if !skipStart! leq %endOffset% (
        for /l %%n in (!skipStart!,1,!skipEnd!) do %callMacro% ("41") %addChar%
        %callMacro% ("%%B") %addChar%
        set /a skipStart=skipEnd+2
      )
    )
  )
  for /l %%n in (%skipStart%,1,%endOffset%) do %callMacro% ("41") %addChar%
  if %blockSize%==0 if defined hex (<nul set /p ".=!hex!") & set hex=
  for /l %%n in (1,1,%lnBytes%) do if defined hex %callMacro% ("2space") %addChar%
  del %dummy%
  exit /b
  ::-------------------------------------------------------
  :hexDump.help
    setlocal disableDelayedExpansion
    echo:
    set file="%~f0"
    set beg=
    for /f "tokens=1,* delims=:" %%a in ('findstr /n /r /i /c:"^:hexDump " %file%') do (
      if not defined beg set beg=%%a
    )
    set end=
    for /f "tokens=1 delims=:" %%a in ('findstr /n /r /c:"^[^:]" %file%') do (
      if not defined end if %beg% LSS %%a set end=%%a
    )
    for /f "tokens=1,* delims=[]:" %%a in ('findstr /n /r /c:"^ *:[^:]" /c:"^::[^:]" /c:"^ *::$" %file%') do (
      if %beg% LEQ %%a if %%a LEQ %end% echo: %%b
    )
exit /b 0

Bug fix on 2011-05-22: (" ") appearing above del %dummy% line became ("2space") and reworked top of addChar macro

Dave Benham

Squashman
Expert
Posts: 4484
Joined: 23 Dec 2011 13:59

Re: New function - :hexDump

#5 Post by Squashman » 17 Nov 2012 23:43

This would be really cool if it had a vertical hexdump option.

Code: Select all

DOS TIPS
44525455
4F304903

noprogrammer
Posts: 36
Joined: 29 Oct 2009 11:55

Re: New function - :hexDump

#6 Post by noprogrammer » 01 Oct 2013 08:46

Dave, here comes a beginner's question:

Let's assume I want to write these hex values to a file:

Code: Select all

89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52

In bash I'd simply do:

Code: Select all

echo -en "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x48\x44\52" >bogus.png

Cmd will make things complicated... What I'm after is something like

  • write a binary pattern into a file
  • add (random) binary data to that file

Is there a (simple) way of doing this?

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: New function - :hexDump

#7 Post by dbenham » 29 Jan 2014 19:47

There is not any convenient way to write binary data to a file using only batch. For the longest time we thought it was not possible. But we recently developed methods to do it :D

See Create nul and all ascii characters with only batch. I recommend reading the entire thread. The links at the top may not point to the most up-to-date methods. Plus there are multiple ways to do it scattered throughout the thread.


Dave Benham

einstein1969
Expert
Posts: 960
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: New function - :hexDump

#8 Post by einstein1969 » 04 May 2014 09:05

Hi Dave!

I recently going to this thread for speedup the reading of files. Even bigger files...

In this year I have learning that the Dos could give much more if our mind controls our prejudices.

For speed up this wonderful utility I think that there are two option. One is to create a temporary file "fc /b ...." out the for /F.

And might be useful to the method used in BatchTEE with pipeline and Set /P fast reading. Usefull in multicore system.

Rif: (after second link : triple click for select + click left mouse + open link)
New technic: set /p can read multiple lines from a file
Asynchronous native batch tee script
http://www.dostips.com/forum/viewtopic.php?p=32292#p32292%20%20 [Topic:slice.cmd]

PS: How to bypass the max 2 urls problem? :twisted: (aGerman help!!)

einstein1969
Last edited by einstein1969 on 04 May 2014 11:31, edited 1 time in total.

Squashman
Expert
Posts: 4484
Joined: 23 Dec 2011 13:59

Re: New function - :hexDump

#9 Post by Squashman » 04 May 2014 10:22

einstein1969 wrote:PS: How to bypass the max 2 urls problem? :twisted: (aGerman help!!)

einstein1969

Create a 2nd post.

aGerman
Expert
Posts: 4678
Joined: 22 Jan 2010 18:01
Location: Germany

Re: New function - :hexDump

#10 Post by aGerman » 04 May 2014 10:30

einstein1969 wrote:PS: How to bypass the max 2 urls problem? :twisted: (aGerman help!!)

No way. It's a setting that only the site admin could adjust. The reason for this restriction is to prevent the spreading of loads of links by spam bots and advertisers.
Something like italic slashes enable the plain-text recognition.
http://www.dostips.com/

Code: Select all

http:[i]//[/i]www.dostips.com/

Regards
aGerman

einstein1969
Expert
Posts: 960
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: New function - :hexDump

#11 Post by einstein1969 » 04 May 2014 11:43

Thanks aGerman! The trick work well. I use this!

@Squashman: thanks to you too.

einstein1969

Post Reply