ブロック デバイス上の最初のゼロ以外のバイト (オプションのオフセットから始まる) を見つけて、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 つあります。a
. がファイル/デバイスの末尾に到達したときにwhile
ループを作成するにはどうすればよいでしょうか。 は終了コード を返しますが、代わりに非ゼロの終了コードが返されることを期待していました。b . 読み取られて stdout に返されるバイトが非ゼロかどうかを評価するにはどうすればよいですか。どこかで、bash でもバイトに対して特別な注意を払う必要があると読んだことがあると思いますが、これがこの状況に当てはまるかどうかさえわかりません。break
dd
dd
0
dd
\0
どのように進めればよいか、あるいは目標を達成するための別の方法を提案していただけますか?
答え1
これは次のようにして行うことができますcmp
と比較すると/dev/zero
:
cmp /path/to/block-device /dev/zero
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
これは、ブロックデバイスだけでなく、任意のファイルで機能します。
答え2
スティーブン・キットの回答これは少し無意味になります (より簡潔で、桁違いに高速です)。ただし、別の方法として、デバイスの内容を 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
そのデータが現れる行内の位置を行のアドレスに追加して、最初のゼロ以外のバイトのオフセットを計算する必要があります。