Uso eficiente de dd (buffer muchos bloques, process uno a la vez)

Dado un file, necesito search el número de bloques que coincide con un bloque de input $templateBlock de cierto tamaño $blockSize .

¿Cuál es una forma eficiente de usar dd para lograr esta tarea? El siguiente método es malo y lento porque invoca dd demasiadas veces.

 while [ $i -lt $totalBlocks]; do dd if="$pathToFile" bs=$blockSize count=1 skip=$i | diff $templateBlock - # Increase $count if $? is 0 # Increase $i by 1 done 

Probablemente, la mejor manera para que dd lea $totalSize y para que yo procese solo $blockSize a la vez para que todo se lea. De esta manera, solo tengo que llamar a dd una vez. En otras palabras, he leído todos los bloques (o muchos) a la vez, y puedo procesar cada bloque de a uno por vez. ¿Es posible hacer esto?

Tal vez algo como esto:

 dd if="$pathToFile" bs=$blockSize | for-each-block { diff $templateBlock - # Update $count if $? is 0 } 

Idealmente, quiero usar solo utilidades de shell.
En otras palabras, preferiría no tener que escribir un progtwig usando Python o similar.

En un script de shell, podría ser mejor usar cmp desde diffutils de GNU. Compara los datos por usted e incluso puede omitir los desplazamientos --ignore-initial=SKIP1:SKIP2 para que pueda ejecutar cmp para cada desplazamiento del sector, y saldrá de la primera diferencia que encuentre … que es semi-eficiente, pero aún así, eso es cmp llamadas cmp si desea ejecutarlo para cada sector …

También puede usar grep -abo o strings -td para encontrar posibles candidatos de desplazamiento de bytes para usted, pero eso depende del patrón real que esté buscando. La ventaja de esto sería una llamada de progtwig para search todo en lugar de miles de llamadas (una por sector).

A less que encuentre una utilidad de command-line que haga todo el trabajo por usted, no podrá vencer a un pequeño script de C / Go / Python que busque todo de una vez según sus requisitos …

Por supuesto, tu idea de guion también funciona, pero solo significa llamar nuevamente a dd (o read , o lo que sea) dentro del ciclo para leer un bloque de stdin a la vez, probablemente sea más lento que antes …

Puede usar el command split para ejecutar un "filter" sobre fragments sucesivos de un file y escribir un filter usando cmp , echo y true para get una nueva línea para cada coincidencia exitosa, luego use wc para contarlos. Por ejemplo, si $F es el file, $TB el file de bloque de plantilla y $SZ el tamaño del bloque de plantilla, entonces podría verse como la siguiente línea de command:

 $ split -b $SZ --filter="cmp $TB >& /dev/null && echo ; true" $F | wc -l 

Tenga en count el true que garantiza que la línea de command del filter tenga éxito, y para save la escritura puede usar : lugar, aunque eso no mejora la legibilidad.

Tenga en count también la networkingirección de todos los resultados de cmp , es decir, tanto stdout como stderr, ya que solo su código de retorno es de interés.