Search code examples
shellformattinghexhexdump

Wider hexdump output


I'm a big fan of the default formatting of the hd command. For example:

$ head -c128 /bin/bash |hd
00000000  7f 45 4c 46 02 01 01 00  00 00 00 00 00 00 00 00  |.ELF............|
00000010  03 00 3e 00 01 00 00 00  30 f6 02 00 00 00 00 00  |..>.....0.......|
00000020  40 00 00 00 00 00 00 00  48 ce 11 00 00 00 00 00  |@.......H.......|
00000030  00 00 00 00 40 00 38 00  0b 00 40 00 1d 00 1c 00  |....@.8...@.....|
00000040  06 00 00 00 04 00 00 00  40 00 00 00 00 00 00 00  |........@.......|
00000050  40 00 00 00 00 00 00 00  40 00 00 00 00 00 00 00  |@.......@.......|
00000060  68 02 00 00 00 00 00 00  68 02 00 00 00 00 00 00  |h.......h.......|
00000070  08 00 00 00 00 00 00 00  03 00 00 00 04 00 00 00  |................|
00000080

I'm looking for a hexdump command that does the same thing but is double-wide. Output should look something like:

$ head -c128 /bin/bash |2hd
00000000  7f 45 4c 46 02 01 01 00  00 00 00 00 00 00 00 00  03 00 3e 00 01 00 00 00  30 f6 02 00 00 00 00 00  |.ELF............| |..>.....0.......|
00000020  40 00 00 00 00 00 00 00  48 ce 11 00 00 00 00 00  00 00 00 00 40 00 38 00  0b 00 40 00 1d 00 1c 00  |@.......H.......| |....@.8...@.....|
00000040  06 00 00 00 04 00 00 00  40 00 00 00 00 00 00 00  40 00 00 00 00 00 00 00  40 00 00 00 00 00 00 00  |........@.......| |@.......@.......|
00000060  68 02 00 00 00 00 00 00  68 02 00 00 00 00 00 00  08 00 00 00 00 00 00 00  03 00 00 00 04 00 00 00  |h.......h.......| |................|
00000080

So far, I've got this. It does not line up properly.

2hd() {
  local poe='"  " 8/1 "%02x "'  # pieces of eight, heh
  hexdump -e '"%07.7_Ax\n"' \
          -e '"%07.7_ax" '"$poe $poe $poe $poe"' "  |" 32/1 "%_p" "|\n"' "$@"
}
$ head -c128 /bin/bash |2hd
0000000  7f 45 4c 46 02 01 01 00  00 00 00 00 00 00 00 00  03 00 3e 00 01 00 00 00  30 f6 02 00 00 00 00 00  |@.......H...........@.8...@.....|
0000040  06 00 00 00 04 00 00 00  40 00 00 00 00 00 00 00  40 00 00 00 00 00 00 00  40 00 00 00 00 00 00 00  |h.......h.......................|
0000080  a8 02 00 00 00 00 00 00  a8 02 00 00 00 00 00 00  a8 02 00 00 00 00 00 00  1c 00 00 00 00 00 00 00  |................................|
00000c0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  98 cd 02 00 00 00 00 00  98 cd 02 00 00 00 00 00  |................................|
0000100

(I haven't decided whether or not I want the right-side display to be in one part or two.)

I'm hoping to do this entirely within a single reference to hexdump. It'd help to know what the hexdump command to get the 16-col hd output would look like too. (The docs I can find are not helpful at this.)


Solution

  • I think you may just need to split the second -e:

    2hd() {
      local poe='"  " 8/1 "%02x "'
      hexdump -e '"%07.7_Ax\n"' \
              -e '"%07.7_ax" '"$poe $poe $poe $poe" \
              -e ' "  |" 32/1 "%_p" "|\n"' "$@"
    }
    

    Multiple -e each work on the same input. In your original, the %_p applies to the input after the %x because it is in the same -e.


    busybox hexdump source defines -C as:

    bb_dump_add(dumper, "\"%08.8_Ax\n\""); // final address line after dump
    //------------------- "address  "   8 * "xx "    "  "  8 * "xx "
    bb_dump_add(dumper, "\"%08.8_ax  \"8/1 \"%02x \"\"  \"8/1 \"%02x \"");
    //------------------- "  |ASCII...........|\n"
    bb_dump_add(dumper, "\"  |\"16/1 \"%_p\"\"|\n\"");
    

    so that means you can implement hd as:

    hexdump -e "\"%08.8_Ax\n\"" -e "\"%08.8_ax  \"8/1 \"%02x \"\"  \"8/1 \"%02x \"" \
            -e "\"  |\"16/1 \"%_p\"\"|\n\""