如何将 hexdump 格式化为 xxd,可以用于 xxd -revert?

如何将 hexdump 格式化为 xxd,可以用于 xxd -revert?

我希望将 SD 卡的原始内容转储到文件中以供检查。它的大部分都是零。学习自这个超级用户的回答我可以用 来显示和pv的进度。预计到达时间都是 1.5 小时。odhexdump

# pv /dev/sdd | od -x --endian=big > sdd_file
... ... ... [>                                     ] ... ETA 1:34:42

# pv /dev/sdd | hexdump -C > sdd_file
... ... ... [>                                     ] ... ETA 1:35:01

不过xxd需要11个小时。

# pv /dev/sdd | xxd -a -u > sdd_file
... ... ... [>                                     ] ... ETA 10:48:53

我更喜欢xxd主要是因为-revert可能性。但xxd处理磁盘需要很长时间。如何格式化hexdump(或od)产生相同格式的文件xxd,使文件可以被-reverted通过xxd

答案1

有的说 xxd -r也接受hexdump输出作为输入。但我测试了一下并非如此。此外,如果该文件也用作备份,则最好采用更有保证的(即完全相同的原始)格式。

感谢来自的灵感这个答案我了解了如何格式化hexdump.

TL;DR - 解决方案

pv /dev/sdd | hexdump -e '"%08.8_ax: "' -e '2/1 "%02X" " " 2/1 "%02X" " " 2/1 "%02X" " " 2/1 "%02X" " " 2/1 "%02X" " " 2/1 "%02X" " " 2/1 "%02X" " " 2/1 "%02X" " "' -e '" " 16/1 "%_p" "\n"' > sdd_file

并进行了一些修复。

请注意。 - 如果磁盘大部分被清零,这些方法会生成一个非常小的文件,类似于压缩。否则,输出文件大约是磁盘大小的 4 倍。请注意您的驱动器是否有足够的可用空间。

测试一下

准备文件。

# echo '- - - - Create a really large file of zeroes - - - -'
# dd bs=1100000000 count=4 if=/dev/zero of=test
4+0 records in
4+0 records out
4400000000 bytes (4.4 GB, 4.1 GiB) copied, 8.71123 s, 505 MB/s

# echo '- - - - Overwrite it with some letters in the beginning (without \n) - - - -'
# echo -n "ABCD xyz" > letters
# dd if=letters of=test conv=notrunc

# echo '- - - - Append some letters in the end (with \n) - - - -'
# echo "ABCD xyz" >> test

输出什么xxd -a -u

# pv test | xxd -a -u > test_xxd
4.10GiB 0:05:39 [12.3MiB/s] [====================================================>] 100%

# cat test_xxd
00000000: 4142 4344 2078 797A 0000 0000 0000 0000  ABCD xyz........
00000010: 0000 0000 0000 0000 0000 0000 0000 0000  ................
*
10642ac00: 4142 4344 2078 797A 0A                   ABCD xyz.

(我的解决方案)如何hexdump ...模拟输出。

# pv test | hexdump -e '"%08.8_ax: "' -e '2/1 "%02X" " " 2/1 "%02X" " " 2/1 "%02X" " " 2/1 "%02X" " " 2/1 "%02X" " " 2/1 "%02X" " " 2/1 "%02X" " " 2/1 "%02X" " "' -e '" " 16/1 "%_p" "\n"' > test_hexdump
4.10GiB 0:00:29 [ 144MiB/s] [====================================================>] 100%

# cat test_hexdump
00000000: 4142 4344 2078 797A 0000 0000 0000 0000  ABCD xyz........
00000010: 0000 0000 0000 0000 0000 0000 0000 0000  ................
*
10642ac00: 4142 4344 2078 797A 0A                   ABCD xyz.

比较它们。

# diff -s test_xxd test_hexdump
Files test_xxd and test_hexdump are identical

解释

格式语法写得很好hexdump 手册页

   A format string contains any number of format units, separated by
   whitespace. A format unit contains up to three items: an
   iteration count, a byte count, and a format.

   The iteration count is an optional positive integer, which
   defaults to one. Each format is applied iteration count times.

   The byte count is an optional positive integer. If specified it
   defines the number of bytes to be interpreted by each iteration
   of the format.

   If an iteration count and/or a byte count is specified, a single
   slash must be placed after the iteration count and/or before the
   byte count to disambiguate them. Any whitespace before or after
   the slash is ignored.

我的解决方案包含三个格式字符串,后面都跟有-e选项。

-e '"%08.8_ax: "'

正如手册页中提到的,格式单位是{ { iteration_count:1 / } byte_count } format.在这种情况下,迭代计数和字节计数都被省略。_a以 he 格式打印偏移字节x%08.8表示它占用 8 个字符并且前面有零。 (实际上就%08_ax可以了。)

-e '2/1 "%02X" " " ... ... ... ... ... '

第二格式字符串是格式单元的重复2/1 "%02X" " "8次;有8列。2/1意思是2次消耗1个字节。这可确保输出十六进制采用大端格式。如果我们消耗 2 个字节并将其转换为十六进制,则右侧的字节将被视为最高有效字节(#1)。与我们的编号系统以及我们的直觉感知相反,输出将出现交换。

该格式"%02X"意味着将其显示为大写 HE X2字符宽度,左填充0

" "实际上是另一种格式单元,省略了迭代计数和字节计数。它在每 2 个字节之间添加一个空格。

然后这组格式单元重复8次,打印8列。

#1 -hexdump默认情况下使用 CPU 的字节顺序 (参考),其中 x86 / x64 CPU 使用具有 16 位大小字的小端字节序。

-e '" " 16/1 "%_p" "\n"'

最后,第三个格式字符串仅以空格开头" "。然后后面跟着一个格式单元16/1 "%_p"。同样,它1一次消耗一个字节,并迭代多次16%_p输出默认字符集中的字符,就像hexdump -C默认xxd情况下通常所做的那样。该格式字符串的第三个格式单元\n仅输出一个换行符。

当形势对我们不利时

有两件事我们需要解决。

TL;DR - (1) 如有必要,添加回最后一行。 (2) 添加回重复的非空行。

观察它们的跳行算法之间的差异。

# xxd -a -u test
00000000: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000010: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000020: 4142 4344 2078 797A 0000 0000 0000 0000  ABCD xyz........
00000030: 4142 4344 2078 797A 0000 0000 0000 0000  ABCD xyz........
00000040: 0000 0000 0000 0000 0000 0000 0000 0000  ................
*
00000070: 4142 4344 2078 797A 0000 0000 0000 0000  ABCD xyz........
00000080: 4142 4344 2078 797A 0000 0000 0000 0000  ABCD xyz........
00000090: 4142 4344 2078 797A 0000 0000 0000 0000  ABCD xyz........
000000a0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
000000b0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
000000c0: 0000 0000 0000 0000 0000 0000 0000 0000  ................

# hexdump -C test
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000020  41 42 43 44 20 78 79 7a  00 00 00 00 00 00 00 00  |ABCD xyz........|
*
00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000070  41 42 43 44 20 78 79 7a  00 00 00 00 00 00 00 00  |ABCD xyz........|
*
000000a0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000000d0

xxd

  1. xxd 总是打印最后一行。最后一行不包括在重复行考虑范围内。
  2. 为了三个或更多重复空行,xxd跳过连续行。
  3. 恢复时,xxd仅将星号 (*) 恢复为空行。xxd不会将星号视为重复的非空行。这是因为xxd一开始就不会跳过非空行。
  4. 即使在规则(2)中,如果有两个连续的空行,xxd也不会跳过其中任何一个。然而,在恢复时,xxd接受一个问号以仅恢复到一个空行。xxd处理得很好。(我们稍后会证明这一点。)

hexdump

  1. hexdump总是打印多一行使用默认格式时的文件字节数。这就是为什么hexdump如果最后一行是重复行,则可以跳过它。
  2. 为了两个或更多重复空或非空行,hexdump跳过连续行。

我们的解决方案的演示。

# pv test | hexdump -e '"%08.8_ax: "' -e '2/1 "%02X" " " 2/1 "%02X" " " 2/1 "%02X" " " 2/1 "%02X" " " 2/1 "%02X" " " 2/1 "%02X" " " 2/1 "%02X" " " 2/1 "%02X" " "' -e '" " 16/1 "%_p" "\n"' > output
 208 B 0:00:00 [1.00MiB/s] [==================================>] 100%
# cat output
00000000: 0000 0000 0000 0000 0000 0000 0000 0000  ................
*
00000020: 4142 4344 2078 797A 0000 0000 0000 0000  ABCD xyz........
*
00000040: 0000 0000 0000 0000 0000 0000 0000 0000  ................
*
00000070: 4142 4344 2078 797A 0000 0000 0000 0000  ABCD xyz........
*
000000a0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
*  

两个修复。

  1. 如果最后一行是星号,则表示最后一行被 跳过hexdump。我们必须计算字节偏移量,即文件(或磁盘)大小减去 16 字节(即 0x10)。添加回最后一行,或者用最后一行替换星号。
  2. 如果星号之前的行不是空行,则表示hexdump跳过非空行。我们必须添加回这些非空重复行。
  3. 请注意,添加最后一行时,可能需要空行或非空行。

要查找磁盘大小,我们可以使用lsblk -b.

修复后。

# vi output
# cat output
00000000: 0000 0000 0000 0000 0000 0000 0000 0000  ................
*
00000020: 4142 4344 2078 797A 0000 0000 0000 0000  ABCD xyz........
00000030: 4142 4344 2078 797A 0000 0000 0000 0000  ABCD xyz........
00000040: 0000 0000 0000 0000 0000 0000 0000 0000  ................
*
00000070: 4142 4344 2078 797A 0000 0000 0000 0000  ABCD xyz........
00000080: 4142 4344 2078 797A 0000 0000 0000 0000  ABCD xyz........
00000090: 4142 4344 2078 797A 0000 0000 0000 0000  ABCD xyz........
000000a0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
*
000000c0: 0000 0000 0000 0000 0000 0000 0000 0000  ................

恢复并检查。

# xxd -r output restore

# diff -s test restore
Files test and restore are identical

请注意。在 line00000010:和 line 处000000b0,用星号替换的单个空行可以很好地处理xxd -revert

答案2

你可以简单地使用下面的东西

  1. 获取所需格式的十六进制转储

    hexdump -Cv <二进制文件.bin> > 二进制文件.txt

-C 将逐字节打印数据

-v 不会使用 * 来表示重复的内容

  1. 现在您需要从 binary_file.txt 中每行删除第一个和最后几个字符。您可以在这里使用 sed 命令。

  2. 现在使用xxd命令

    xxd -r -p 二进制文件.txt > 恢复二进制文件.bin

  3. 您可以检查两个文件的 md5sum。它应该匹配

    md5sum 二进制文件.bin

    md5sum 恢复二进制文件.bin

相关内容