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でもバイトに特別な注意を払わなければならないという内容をどこかで読んだようです。しかし、これがこの場合に適しているかどうかはわかりません。break
dd
dd
0
dd
\0
進行方法に関するいくつかのヒントや目標を達成するための提案と代替案を提供できますか?
答え1
以下を使用してこれを実行できます。cmp
、比較する/dev/zero
:
cmp /path/to/block-device /dev/zero
cmp
ゼロ以外の最初のバイトのオフセットを提供します。
バイトをスキップするにはGNUオプションを使用できます。GNUを使用しない場合は、次のようにcmp
適切なデータを提供できます。-i
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
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
アドレスにその行の発生項目を追加して、ゼロ以外の最初のバイトのオフセットを計算する必要があります。