pasar dd skip | buscar desplazamiento como hexadecimal

11
# dd if=2013-Aug-uptime.csv bs=1 count=1 skip=3 2> /dev/null
d
# dd if=2013-Aug-uptime.csv bs=1 count=1 skip=0x3 2> /dev/null
f

¿Por qué el segundo comando genera un valor diferente?

¿Es posible pasar el desplazamiento skip | seek ddcomo un valor hexadecimal?

Eadmaster
fuente

Respuestas:

18

¿Por qué el segundo comando genera un valor diferente?

Por razones históricas, se ddconsidera xun operador de multiplicación. Entonces 0x3se evalúa como 0.

¿Es posible pasar el desplazamiento skip | seek a dd como un valor hexadecimal?

No directamente, que yo sepa. Además de la multiplicación con el operador x, puede sufijar cualquier número con el bsignificado de "multiplicar por 512" (0x200) y con el Ksignificado de "multiplicar por 1024" (0x400). Con GNU dd también puede utilizar sufijos M, G, T, P, E, Zy Yen el sentido de multiplicar por 2 a la potencia de 20, 30, 40, 50, 60, 70, 80 o 90, respectivamente, y se puede utilizar en mayúsculas o minúsculas, excepto para el bsufijo (Hay muchos otros sufijos posibles. Por ejemplo, EBsignifica "multiplicar por 10 18 " y PiBsignifica "multiplicar por 2 50 ". Consulte info coreutils "block size"para obtener más información, si tiene una instalación GNU).

Puede encontrar lo arcano, anacrónico y geek anterior hasta el punto de lo absurdo. No te preocupes: no estás solo. Afortunadamente, puede ignorarlo todo y utilizar la sustitución aritmética de su shell (bash y otros shells compatibles con Posix funcionarán, así como algunos shells que no sean Posix). El shell entiende los números hexadecimales, y permite un rango completo de operadores aritméticos escritos de la manera normal. Solo necesita rodear la expresión con $((...)):

# dd if=2013-Aug-uptime.csv bs=1 count=$((0x2B * 1024)) skip=$((0x37))
rici
fuente
Tenga en cuenta que $((...))es la expansión aritmética POSIX, no es bash específico en absoluto, no tiene que usarlo bashpara usarlo, cualquier shell POSIX lo hará. Sin embargo, tenga en cuenta que en muchos shells bash, incluso , se divide la palabra, por lo que debe citarse.
Stéphane Chazelas
@StephaneChazelas: Eso es cierto, no es específico de bash. Sin embargo, no necesita comillas. (Posix: "La expresión se tratará como si estuviera entre comillas dobles, excepto que una comilla doble dentro de la expresión no se trata especialmente".) Si hubiera una variable en la expresión y su valor incluyera un separador, entonces no sería un número válido; poner comillas alrededor $((...))no cambiará nada. El único caso en el que puedo pensar dónde las citas harían algo es si tuvieras algo así, IFS=4pero eso causaría todo tipo de otro caos.
rici
La sección que cita es sobre lo que hay dentro $((...)). POSIX es claro que la expansión de $((...))está sujeta a la división de palabras . Dejar cualquiera de las expansiones de comando / aritmética / variable sin comillas en el contexto de la lista es el operador split + glob. Establecer IFS = 4 no causaría todo tipo de problemas si no usa el operador split + glob donde no es necesario / deseado, y establece IFS cada vez que necesita ese operador split + glob.
Stéphane Chazelas
@StephaneChazelas: sí, el resultado numérico está sujeto a división de palabras. Pero es un número entero. Si establece IFSalgo que incluye dígitos, algo que no creo haber hecho alguna vez, entonces deberá citarlo. Presumiblemente, si uno estuviera haciendo eso, estaría al tanto de la necesidad, ya que difícilmente es algo que uno pueda hacer casualmente. O, al menos, no es algo que pueda hacer, punto. No quiero hablar por ti.
rici
1
@ogurets: ¿qué caparazón estás usando? (Incluya la versión).
rici
0

Sé que este es un hilo viejo, pero el problema sigue siendo tan relevante como siempre, especialmente cuando idiotas como yo van y recuerdan y ejecutan inadvertidamente un 'cp ​​fileA fileB' del historial de bash cuando el archivo B aún no se ha registrado para que git no esté respaldado y que contiene varias horas de codificación después de una noche entera: - /

Gracias a los conceptos de este hilo pude recuperar completamente mi archivo perdido, sin embargo, perdí el mío en un servidor privado virtual remoto con un disco de 32 Gb y muy poca RAM (ejecutando Ubuntu 18.04), y todos mis intentos usando 'grep' como arriba moriría rápidamente con 'memoria insuficiente'

En mi caso fue lo hexdump -C /dev/sdX1 | grep 'shortString'que vino a mi rescate. A diferencia de grep, solo muestra una representación ASCII muy narroy del hex, por lo que es vital buscar solo una cadena corta y única, y tener en cuenta que incluso eso podría estar envuelto. Una vez que había emitido alguna dirección hexadecimal donde había una coincidencia, pude usar 'dd' de una manera similar a la anterior, excepto que encontré que parecía estar predeterminado a un tamaño de bloque de 4096, por lo que no solo tuve que convierta la dirección de bytes hexadecimales a decimal, pero divídala por 4096 para escalarla a 4k bloques para el parámetro de omisión de dd; sin ayuda, si este número es demasiado grande para dd, el mensaje de error parece que se queja de skip=ser inválido en lugar del número que se le pasó .

Felicitaciones a las personas que agregaron consejos sobre el uso de bash con $((0xabcd))para obtener fácilmente la conversión hexadecimal-> dec :-)

Solo mi última palabra: en mi caso, había varias copias del mismo archivo que estaban muy cerca. Pero restando la dirección más baja de la dirección más alta informada por hexdump pude identificar una región de ~ 5 MB que contenía todas las copias posibles, lo que significaba que podía apuntar dd a la dirección más baja y extraer toda esa región a un archivo temporal. El editor Vim ahora maneja el contenido binario con bastante gracia para que pueda examinar el archivo temporal y remodelarlo según sea necesario.

JonathanH-UK
fuente