Bash

如何在塊設備上找到第一個非零字節,並帶有可選的偏移量?

  • June 2, 2021

我正在嘗試使用並列印其偏移量的塊設備上的第一個非零字節(從可選偏移量開始)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循環?給出一個退出程式碼,而我期望一個非零退出程式碼。 灣。如何評估在標準輸出上讀取和返回的字節是否非零?我想我在某處讀到過,在 bash 中也應該特別注意字節,但我什至不確定這是否與這種情況有關。break``dd``dd``0
dd``\0

你能給我一些關於如何進行的提示,或者建議和替代方法來實現我的目標嗎?

您可以使用 來執行此操作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

這適用於任何文件,而不僅僅是塊設備。

斯蒂芬基特的回答使這有點毫無意義(它更簡潔,速度快一個數量級以上),但您可以選擇(十六進制)轉儲設備的內容,每行一個字節,並將其通過管道傳輸到列印第一個字節的地址的程序,它的表示不是00,並在找到它後立即退出:

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

od-j選項允許您有選擇地選擇要跳過的字節數(在輸入的開頭)。

更快的變化(感謝Peter Cordes的評論)需要更多的輸入:

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

允許od以首選格式輸出數據需要計算第一個非零字節的偏移量,方法是將其在行中出現的位置添加到行地址。

引用自:https://unix.stackexchange.com/questions/652331