선택적 오프셋을 사용하여 블록 장치에서 0이 아닌 첫 번째 바이트를 어떻게 찾나요?

선택적 오프셋을 사용하여 블록 장치에서 0이 아닌 첫 번째 바이트를 어떻게 찾나요?

오프셋 을 사용하여 블록 장치에서 0이 아닌 첫 번째 바이트(선택적 오프셋에서 시작)를 찾아 인쇄하려고 하는데 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루프를 만드나요 ? 의 종료 코드를 제공하는데 , 대신 0이 아닌 종료 코드가 예상됩니다. 비. stdout에서 읽고 반환하는 바이트가 0이 아닌지 어떻게 평가합니까 ? 나는 바이트를 사용하는 bash에서도 특별한 주의를 기울여야 한다고 어딘가에서 읽은 것 같지만 이것이 이 상황과 관련이 있는지조차 확신할 수 없습니다.breakdddd0
dd\0

진행 방법에 대한 힌트를 주실 수 있습니까? 아니면 제 목표를 달성하기 위한 대체 방법을 제안해 주실 수 있나요?

답변1

다음을 사용하여 이 작업을 수행할 수 있습니다.cmp, 다음과 비교 /dev/zero:

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

cmp0이 아닌 첫 번째 바이트의 오프셋을 제공합니다.

바이트를 건너뛰려면 GNU 옵션을 사용할 수 있고 cmp, -iGNU를 사용하지 않는 경우 다음을 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

스티븐 키트의 답변이것은 약간 무의미하게 만듭니다(더 간결하고 10배 이상 빠릅니다). 그러나 대안은 장치의 내용을 한 줄에 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해당 줄의 주소에 나타나는 줄의 위치를 ​​추가하여 0이 아닌 첫 번째 바이트의 오프셋을 계산해야 합니다.

관련 정보