如何使用可选偏移量在块设备上找到第一个非零字节?

Exp*_*est 11 bash dd block-device byte

我正在尝试使用dd并打印其偏移量在块设备上找到第一个非零字节(从可选偏移量开始),但我被卡住了。我没有dd在标题中提及,因为我认为可能有比dd这样做更合适的工具,但我认为dd应该是一个好的开始。如果您知道更合适的工具和/或更有效的方法来实现我的目标,那也没关系。

与此同时,我将向您展示我dd在 bash 方面的进展,到目前为止。

#!/bin/bash

# infile is just a temporary test file for now, which will be replaced with /dev/sdb, for instance
infile=test.txt
offset=0

while true; do
  byte=`dd status='none' bs=1 count=1 if="$infile" skip=$offset`
  ret=$?

  # the following doesn't appear to work
  # ret is always 0, even when the end of file/device is reached
  # how do I correctly determine if dd has reached the end of file/device?
  if [ $ret -gt 0 ]; then
    echo 'error, or end of file reached'
    break
  fi

  # I don't know how to correctly determine if the byte is non-zero
  # how do I determine if the read byte is non-zero?
  if [ $byte ???? ]; then
    echo "non-zero byte found at $offset"
    break
  fi

  ((++offset))
done


Run Code Online (Sandbox Code Playgroud)

如您所见,我遇到了两个我不知道如何解决的问题:
a。到达文件/设备的末尾时如何进行while循环?给出一个退出代码,我期望一个非零退出代码。 湾 如何评估在 stdout 上读取和返回的字节是否为非零?我想我在某个地方读到过,在 bash 中也应该特别注意字节,但我什至不确定这是否与这种情况有关。breakdddd0
dd\0

你能给我一些关于如何进行的提示,或者建议和替代方法来实现我的目标吗?

Ste*_*itt 30

cmp与 相比,您可以使用 来执行此操作/dev/zero

cmp /path/to/block-device /dev/zero
Run Code Online (Sandbox Code Playgroud)

cmp 会给你第一个非零字节的偏移量。

如果您想跳过字节,您可以使用 GNUcmp-i选项,或者如果您不使用 GNU cmp,请使用dd以下方法为其提供适当的数据:

cmp -i 100 /path/to/block-device /dev/zero
dd if=/path/to/block-device bs=1 skip=100 | cmp - /dev/zero
Run Code Online (Sandbox Code Playgroud)

这适用于任何文件,而不仅仅是块设备。

  • 非常聪明!对于那些不限制使用 bash 的人,另见 ksh93 中的 `cmp < /path/to/block-device <#((100)) - /dev/zero`(或与 `zsh` 中的 `sysseek` 等效)。 (6认同)
  • 这确实非常聪明——最后是 /dev/zero 的有用用法! (2认同)

fra*_*san 8

Stephen Kitt 的回答使这有点毫无意义(它更简洁,速度超过一个数量级),但您拥有的另一种选择是(十六进制)转储设备的内容,每行一个字节,并将其通过管道传输到打印第一个字节的地址的程序,它的表示不是,00并在找到它后立即退出:

od -Ad -w1 -tx1 /dev/device | awk '$2 && $2 != "00" { print $1 + 1; exit }'
Run Code Online (Sandbox Code Playgroud)

od-j选项允许您有选择地选择要跳过的字节数(在输入的开头)。

更快的变化(感谢Peter Cordes的评论)需要更多的输入:

od -Ad -tx1 | awk '
  {
    for (i=2; i<=NF; i++)
      if ($i != "00") {
        print ($1 + i -1)
        exit
      }
  }'
Run Code Online (Sandbox Code Playgroud)

允许od以其首选格式输出数据需要通过将其在其出现的行中的位置添加到该行的地址来计算第一个非零字节的偏移量。

  • @PeterCordes `od` 默认也会折叠重复的值(我选择它是因为它是 POSIX;虽然我看到 `hexdump` 可能更快)。它并不是慢得令人难以忍受,因为这里的目标允许将发射的线限制为最多三个。 (2认同)