Cómo eliminar parte de un file binary sin copyr

Necesito eliminar los primeros 2 bytes de un file de 6MB. Sin embargo, este es un Linux embebido con solo 32 Mbytes de RAM y less de 1 MB de memory flash gratuita.

Intenté usar dd, como:

1 – # dd bs=1 skip=2 count=1022 if=input of=ouput_1

2 – # dd bs=1024 skip=1 if=input of=ouput_2

3 – rm -rf input # rm -rf input

4 – # (dd if=ouput_1 ; dd if=ouput_2) > ouput

5 – # rm -rf ouput_1 ouput_2

Con todos los files bajo / tmp (montado como tmpfs en la RAM), mi problema es que justo antes de las líneas 3 y 5, la memory necesaria es de 12 Mbyte (2x6MB), y el process a veces falla y produce un error de "Falta de memory suficiente" .

¿Hay alguna manera de eliminar los primeros 2 bytes sin asignar el doble del tamaño del file? ¿Puedo usar dd (o cualquier otro) para cortar un file binary 'en su lugar'?

Creo que esto debería funcionar:

 $ # Create test file $ echo "Hello, World" > h.data $ $ # Move contents up by 2 bytes $ # Note if= and of= are the same for in-place editing $ dd bs=2 if=h.data skip=1 seek=0 conv=notrunc of=h.data 5+1 records in 5+1 records out 11 bytes (11 B) copied, 0.000598796 s, 18.4 kB/s $ $ # Note 11 bytes were moved above $ # Truncate the file after byte 11 $ dd bs=11 if=h.data skip=1 seek=1 count=0 of=h.data 0+0 records in 0+0 records out 0 bytes (0 B) copied, 0.000338852 s, 0.0 kB/s $ $ # Display edited file: $ cat h.data llo, World $ 

Envolviendo todo esto en un script podrías tener algo como esto:

 #!/bin/bash size=$(stat -c %s "$2") dd bs=$1 if="$2" skip=1 seek=0 conv=notrunc of="$2" dd bs=$((size - $1)) if="$2" skip=1 seek=1 count=0 of="$2" 

Llamar esto como:

 ./truncstart.sh 2 file.dat 

Donde 2 es el número de bytes para eliminar desde el principio de file.data


Como señala @Gilles, esta solución no es robusta en caso de una interrupción no planificada, que podría ocurrir en el process de dd ; en cuyo caso el file estaría dañado.

Basado en la respuesta de @DigitalTrauma, esto es lo que funcionó para mí por fin:

 size=$(stat -c %s file) dd bs=2 if=file skip=1 seek=0 conv=notrunc count=511 of=file dd if=file ibs=1024 skip=1 of=file conv=notrunc obs=1022 seek=1 truncate file $(( size - 2 )) 

La eliminación de los dos primeros bytes se realiza en 2 dd pasos para acelerar las cosas y truncate es una pequeña utilidad para truncar los últimos bytes del file:

 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> int main(int argc, char **argv) { if (argc != 3 ) { printf ("Usage: %s <file> <bytes>\n", argv[0]); exit(1); } if (truncate(argv[1], atoi(argv[2]))) { printf (" Error ! \n"); exit(1); } return(0); }