我試圖使用並列印其偏移量來查找區塊設備上的第一個非零位元組(從可選偏移量開始)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
正如您所看到的,我遇到了兩個不知道如何解決的問題
:到達文件/設備末尾時如何進行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
史蒂芬·基特的回答使這有點毫無意義(它更簡潔,速度快一個數量級以上),但您擁有的另一種選擇是(十六進制)轉儲設備的內容,每行一個字節,並將其通過管道傳輸到列印的程式其表示形式不是的第一個位元組的位址,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
以其首選格式輸出資料需要透過將其在行中出現的位置新增至行位址來計算第一個非零位元組的偏移量。