Así es como puedes hacer esto:
i=$(((t=19876543212)-(h=12345678901)))
{ dd count=0 skip=1 bs="$h"
dd count="$((i/(b=64*1024)-1))" bs="$b"
dd count=1 bs="$((i%b))"
} <infile >outfile
Eso es todo lo que es realmente necesario: no requiere mucho más. En primer lugar dd count=0 skip=1 bs=$block_size1
, lseek()
sobre la entrada de archivos regulares prácticamente de forma instantánea. No hay posibilidad de que se pierdan datos o de cualquier otra falsedad que se les diga, solo puede buscar directamente a su posición de inicio deseada. Debido a que el descriptor de archivo es propiedad del shell y los dd
's simplemente lo heredan, afectarán la posición del cursor y, por lo tanto, puede seguirlo paso a paso. Realmente es muy simple, y no existe una herramienta estándar más adecuada para la tarea que dd
.
Utiliza un tamaño de bloque de 64k que a menudo es ideal. Contrariamente a la creencia popular, los bloques de mayor tamaño no hacen que el dd
trabajo sea más rápido. Por otro lado, los amortiguadores pequeños tampoco son buenos. dd
necesita sincronizar su hora en las llamadas al sistema para que no tenga que esperar para copiar datos en la memoria y volver a salir, sino también para que no tenga que esperar en las llamadas del sistema. Por lo tanto, desea que tome el tiempo suficiente para que el siguiente read()
no tenga que esperar al último, pero no tanto como para almacenar en búfer en tamaños más grandes de lo necesario.
Entonces el primero dd
salta a la posición inicial. Eso lleva cero tiempo. Puede llamar a cualquier otro programa que le haya gustado en ese momento para leer su stdin y comenzaría a leer directamente en el desplazamiento de bytes deseado. Llamo a otro dd
para leer los ((interval / blocksize) -1)
bloques de conteo para stdout.
Lo último que es necesario es copiar el módulo (si lo hay) de la operación de división anterior. Y eso es eso.
No lo creas, por cierto, cuando las personas declaran hechos sin evidencia. Sí, es posible dd
hacer una lectura corta (aunque tales cosas no son posibles cuando se lee desde un dispositivo de bloque sano , de ahí el nombre) . Tales cosas solo son posibles si no almacena correctamente una dd
secuencia que se lee desde otro dispositivo que no sea un bloque. Por ejemplo:
cat data | dd bs="$num" ### incorrect
cat data | dd ibs="$PIPE_MAX" obs="$buf_size" ### correct
En ambos casos, dd
copia todos los datos. En el primer caso, es posible (aunque improbable cat
) que algunos de los bloques de salida que se dd
copian serán iguales a "$ num" bytes porque solodd
se especifica para almacenar algo cuando el buffer se solicita específicamente en su comando. línea. representa un tamaño de bloque máximo porque el propósito de es E / S en tiempo real.bs=
dd
En el segundo ejemplo, especifico explícitamente el tamaño de bloque de salida y las dd
lecturas de almacenamiento intermedio hasta que se puedan realizar escrituras completas. Eso no afecta lo count=
que se basa en bloques de entrada, pero para eso solo necesita otro dd
. Cualquier información errónea que se le proporcione de otra manera no se tendrá en cuenta.
bs=1M iflag=skip_bytes,count_bytes