オプションのオフセットを使用してブロックデバイスでゼロ以外の最初のバイトを見つける方法は?

オプションのオフセットを使用してブロックデバイスでゼロ以外の最初のバイトを見つける方法は?

offsetを使用して印刷するブロックデバイス(オプションのオフセットから始まる)で、ゼロ以外の最初のバイトを探そうと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


ご覧のとおり、解決策がわからない2つの問題に直面しました
。ファイル/デバイスの終わりに達したら、どのように繰り返しますかwhile?提供された終了コードですが、ゼロ以外の終了コードを予想しました。 b。 stdoutから読み込み、返されたバイトがゼロでないかどうかを評価する方法は? Bashでもバイトに特別な注意を払わなければならないという内容をどこかで読んだようです。しかし、これがこの場合に適しているかどうかはわかりません。breakdddd0
dd\0

進行方法に関するいくつかのヒントや目標を達成するための提案と代替案を提供できますか?

答え1

以下を使用してこれを実行できます。cmp、比較する/dev/zero

cmp /path/to/block-device /dev/zero

cmpゼロ以外の最初のバイトのオフセットを提供します。

バイトをスキップするにはGNUオプションを使用できます。GNUを使用しない場合は、次のようにcmp適切なデータを提供できます。-icmpdd

cmp -i 100 /path/to/block-device /dev/zero
dd if=/path/to/block-device bs=1 skip=100 | cmp - /dev/zero

これはブロックデバイスだけでなく、すべてのファイルに適用されます。

答え2

Steven Kitの答えこれをやや無意味にしますが(よ​​りクリーンではるかに高速です)、他のオプションはデバイスの内容を1行に1バイトずつ(16進数)ダンプしてパイプすることです。印刷プログラムに転送されずに印刷プログラムに転送され、見つかるとすぐに終了し00ます。

od -Ad -w1 -tx1 /dev/device | awk '$2 && $2 != "00" { print $1 + 1; exit }'

odオプション-jを使用すると、スキップするバイト数(入力の先頭)を選択できます。

より速い変更(おかげでピーター・コルデス'コメント)には追加の入力が必要です。

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

データをデフォルトの形式で出力するには、行odアドレスにその行の発生項目を追加して、ゼロ以外の最初のバイトのオフセットを計算する必要があります。

関連情報