¿Cómo encuentro el primer byte distinto de cero en un dispositivo de bloque, con un desplazamiento opcional?

¿Cómo encuentro el primer byte distinto de cero en un dispositivo de bloque, con un desplazamiento opcional?

Estoy tratando de encontrar el primer byte distinto de cero (a partir de un desplazamiento opcional) en un dispositivo de bloque usando dde imprimir su desplazamiento, pero estoy atascado. No lo mencioné dden el título porque pensé que podría haber una herramienta más apropiada que ddhacer esto, pero pensé ddque debería ser un buen comienzo. Si conoce una herramienta más adecuada y/o una forma más eficiente de alcanzar mi objetivo, también está bien.

Mientras tanto, les mostraré hasta dónde he llegado dden bash hasta ahora.

#!/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


Como puedes ver, tengo dos problemas que no sé cómo resolver:
a. ¿Cómo hago el whilebucle breakcuando ddhe llegado al final del archivo/dispositivo? ddproporciona un código de salida de 0, donde esperaba un código de salida distinto de cero.
b. ¿Cómo evalúo si el byte que ddse lee y devuelve en la salida estándar no es cero? Creo que leí en alguna parte que \0también se debe tener especial cuidado en bash con los bytes, pero ni siquiera estoy seguro de que esto se relacione con esta situación.

¿Puede darme algunas sugerencias sobre cómo proceder, o quizás sugerirme una forma alternativa de lograr mi objetivo?

Respuesta1

Puedes hacer esto usandocmp, comparado a /dev/zero:

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

cmple dará el desplazamiento del primer byte distinto de cero.

Si desea omitir bytes, puede usar la opción cmpde GNU -i, o si no está usando GNU cmp, proporcione los datos apropiados usando dd:

cmp -i 100 /path/to/block-device /dev/zero
dd if=/path/to/block-device bs=1 skip=100 | cmp - /dev/zero

Esto funcionará con cualquier archivo, no solo con dispositivos de bloqueo.

Respuesta2

La respuesta de Stephen Kitt.hace que esto sea un poco inútil (es más conciso y más de un orden de magnitud más rápido), pero una alternativa que tiene es volcar (hexadecimalmente) el contenido de su dispositivo, un byte por línea, y canalizarlo a un programa que imprima la dirección del primer byte cuya representación no lo es 00y sale tan pronto como lo encuentra:

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

odLa opción de -jle permite seleccionar opcionalmente el número de bytes a omitir (al comienzo de la entrada).

Una variación mucho más rápida (gracias aPedro Cordes'comentarios) requiere un poco más de escritura:

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

Permitir odgenerar datos en su formato preferido requiere calcular el desplazamiento del primer byte distinto de cero agregando su posición en la línea en la que aparece a la dirección de la línea.

información relacionada